making sesman multithread

ulab-original
ilsimo 18 years ago
parent 20e26f1ccd
commit fda836169e

@ -1,9 +1,9 @@
# sesman makefile
SESMANOBJ = sesman.o config.o tcp.o sig.o session.o env.o \
os_calls.o d3des.o list.o file.o log.o access.o \
scp.o scp_v0.o
scp.o scp_v0.o thread.o lock.o
SESRUNOBJ = sesrun.o config.o tcp.o \
SESRUNOBJ = sesrun.o config.o tcp.o lock.o \
os_calls.o d3des.o list.o file.o log.o
DESTDIR = /usr/local/xrdp
@ -15,8 +15,8 @@ DOCDIR = /usr/doc/xrdp
DEFINES = -DSESMAN_CFG_FILE=\"$(CFGDIR)/sesman.ini\" \
-DSESMAN_PID_FILE=\"$(PIDDIR)/sesman.pid\"
CFLAGS = -Wall -O2 -I../common $(DEFINES)
LDFLAGS = -L /usr/gnu/lib $(DEFINES)
CFLAGS = -Wall -O2 -I../common -I/usr/include/nptl $(DEFINES)
LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread $(DEFINES)
C_OS_FLAGS = $(CFLAGS) -c
CC = gcc
@ -70,4 +70,4 @@ file.o: ../common/file.c
$(CC) $(C_OS_FLAGS) ../common/file.c
log.o: ../common/log.c
$(CC) $(C_OS_FLAGS) ../common/log.c
$(CC) $(C_OS_FLAGS) -DLOG_ENABLE_THREAD ../common/log.c

@ -0,0 +1,200 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2006
session manager
linux only
*/
#include "sesman.h"
#include <semaphore.h>
#include <pthread.h>
pthread_mutex_t lock_chain; /* session chain lock */
pthread_mutexattr_t lock_chain_attr; /* mutex attributes */
pthread_mutex_t lock_config; /* configuration access lock */
pthread_mutexattr_t lock_config_attr; /* mutex attributes */
pthread_mutex_t lock_fork; /* this lock protects the counters */
pthread_mutexattr_t lock_fork_attr; /* mutex attributes */
sem_t lock_fork_req; /* semaphore on which the process that are going to fork suspend on */
sem_t lock_fork_wait; /* semaphore on which the suspended process wait on */
int lock_fork_forkers_count; /* threads that want to fork */
int lock_fork_blockers_count; /* threads thar are blocking fork */
int lock_fork_waiting_count; /* threads suspended until the fork finishes */
sem_t lock_socket;
void DEFAULT_CC
lock_init()
{
/* initializing socket lock */
sem_init(&lock_socket, 0, 1);
/* initializing chain lock */
pthread_mutexattr_init(&lock_chain_attr);
pthread_mutex_init(&lock_chain, &lock_chain_attr);
/* initializing config lock */
pthread_mutexattr_init(&lock_config_attr);
pthread_mutex_init(&lock_config, &lock_config_attr);
/* initializing fork lock */
pthread_mutexattr_init(&lock_fork_attr);
pthread_mutex_init(&lock_chain, &lock_fork_attr);
sem_init(&lock_fork_req, 0, 0);
sem_init(&lock_fork_wait, 0, 0);
/* here we don't use locking because lock_init() should be called BEFORE */
/* any thread is created */
lock_fork_blockers_count=0;
lock_fork_waiting_count=0;
lock_fork_forkers_count=0;
}
/******************************************************************************/
void DEFAULT_CC
lock_chain_acquire()
{
/*lock the chain*/
LOG_DBG("lock_chain_acquire()",0);
pthread_mutex_lock(&lock_chain);
}
/******************************************************************************/
void DEFAULT_CC
lock_chain_release()
{
/*unlock the chain*/
LOG_DBG("lock_chain_release()",0);
pthread_mutex_unlock(&lock_chain);
}
/******************************************************************************/
void DEFAULT_CC
lock_socket_acquire()
{
/* lock socket variable */
LOG_DBG("lock_socket_acquire()",0);
sem_wait(&lock_socket);
}
/******************************************************************************/
void DEFAULT_CC
lock_socket_release()
{
/* unlock socket variable */
LOG_DBG("lock_socket_release()",0);
sem_post(&lock_socket);
}
/******************************************************************************/
void DEFAULT_CC
lock_fork_request()
{
/* lock mutex */
pthread_mutex_lock(&lock_fork);
if (lock_fork_blockers_count == 0)
{
/* if noone is blocking fork(), then we're allowed to fork */
sem_post(&lock_fork_req);
}
lock_fork_forkers_count++;
pthread_mutex_unlock(&lock_fork);
/* we wait to be allowed to fork() */
sem_wait(&lock_fork_req);
}
/******************************************************************************/
void DEFAULT_CC
lock_fork_release()
{
pthread_mutex_lock(&lock_fork);
lock_fork_forkers_count--;
/* if there's someone else that want to fork, we let him fork() */
if (lock_fork_forkers_count > 0)
{
sem_post(&lock_fork_req);
}
for (;lock_fork_waiting_count > 0; lock_fork_waiting_count--)
{
/* waking up the other processes */
sem_post(&lock_fork_wait);
}
pthread_mutex_unlock(&lock_fork);
}
/******************************************************************************/
void DEFAULT_CC
lock_fork_critical_section_end(int blocking)
{
LOG_DBG("lock_fork_critical_secection_end()",0);
/* lock mutex */
pthread_mutex_lock(&lock_fork);
if (blocking == SESMAN_LOCK_FORK_BLOCKER)
{
lock_fork_blockers_count--;
}
/* if there's someone who wants to fork and we're the last blocking */
/* then we let him go */
if ((lock_fork_blockers_count == 0) && (lock_fork_forkers_count>0))
{
sem_post(&lock_fork_req);
}
pthread_mutex_unlock(&lock_fork);
}
/******************************************************************************/
int DEFAULT_CC
lock_fork_critical_section_start()
{
LOG_DBG("lock_fork_critical_secection_start()",0);
do
{
pthread_mutex_lock(&lock_fork);
/* someone requested to fork */
if (lock_fork_forkers_count > 0)
{
lock_fork_waiting_count++;
pthread_mutex_unlock(&lock_fork);
/* we wait until the fork finishes */
sem_wait(&lock_fork_wait);
}
else
{
/* no fork, so we can go on... */
lock_fork_blockers_count++;
pthread_mutex_unlock(&lock_fork);
return SESMAN_LOCK_FORK_BLOCKER;
}
} while (1);
/* we'll never get here */
return SESMAN_LOCK_FORK_WAITING;
}

@ -0,0 +1,122 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2006
*/
#ifndef LOCK_H
#define LOCK_H
#include "sesman.h"
#define SESMAN_LOCK_FORK_BLOCKER 1
#define SESMAN_LOCK_FORK_WAITING 0
/**
*
* @brief initializes all the locks
*
*/
void DEFAULT_CC
lock_init();
/**
*
* @brief acquires the lock for the session chain
*
*/
void DEFAULT_CC
lock_chain_acquire();
/**
*
* @brief releases the sessiona chain lock
*
*/
void DEFAULT_CC
lock_chain_release();
/**
*
* @brief acquires config lock
*
*/
void DEFAULT_CC
lock_cfg_acquire();
/**
*
* @brief releases config lock
*
*/
void DEFAULT_CC
lock_cfg_release();
/**
*
* @brief request the socket lock
*
*/
void DEFAULT_CC
lock_socket_acquire();
/**
*
* @brief releases the socket lock
*
*/
void DEFAULT_CC
lock_socket_release();
/**
*
* @brief requires to fork a new child process
*
*/
void DEFAULT_CC
lock_fork_request();
/**
*
* @brief releases a fork() request
*
*/
void DEFAULT_CC
lock_fork_release();
/**
*
* @brief starts a section that is critical for forking
*
* starts a section that is critical for forking, that is noone can fork()
* while i'm in a critical section. But if someone wanted to fork we have
* to wait until he finishes with lock_fork_release()
*
* @return
*
*/
int DEFAULT_CC
lock_fork_critical_section_start();
/**
*
* @brief closes the critical section
*
*/
void DEFAULT_CC
lock_fork_critical_section_end(int blocking);
#endif

@ -29,9 +29,11 @@
#include "sesman.h"
extern int thread_sck;
/******************************************************************************/
void DEFAULT_CC
scp_process_start(int sck)
void* DEFAULT_CC
scp_process_start(void* sck)
{
int socket;
int version;
@ -39,12 +41,14 @@ scp_process_start(int sck)
struct stream* in_s;
struct stream* out_s;
/* making a local copy of the socket */
/* sck should NEVER be used after lock_socket_release() */
/* probably this is just paranoia */
socket = sck;
#warning locking disabled
// lock_socket_release();
/* making a local copy of the socket (it's on the stack) */
/* probably this is just paranoia */
//socket = *((int*) sck);
socket = thread_sck;
LOG_DBG("started scp thread on socket %d", socket);
/* unlocking thread_sck */
lock_socket_release();
make_stream(in_s);
make_stream(out_s);
@ -63,7 +67,7 @@ scp_process_start(int sck)
scp_v0_process(socket, in_s, out_s);
}
#warning scp v1 is disabled
/* this is temporarily disabled...
/* this is temporarily disabled...
else if (version == 1)
{
/ * starts processing an scp v0 connection * /
@ -80,5 +84,6 @@ scp_process_start(int sck)
g_tcp_close(socket);
free_stream(in_s);
free_stream(out_s);
return 0;
}

@ -39,7 +39,7 @@
* @param socket the connection socket
*
*/
void DEFAULT_CC
scp_process_start(int socket);
void* DEFAULT_CC
scp_process_start(void* sck);
#endif

@ -30,48 +30,9 @@
int g_sck;
int g_pid;
unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 };
#ifdef OLDSESSION
struct session_item g_session_items[100]; /* sesman.h */
extern int g_session_count;
#endif
struct config_sesman g_cfg; /* config.h */
//int g_server_type = 0; /* Xvnc 0 Xrdp 10 */
/**
*
* @brief triggered when a child process (a session) dies
* @param s received signal
*
*/
static void DEFAULT_CC
cterm(int s)
{
#ifdef OLDSESSION
int i;
#endif
int pid;
if (g_getpid() != g_pid)
{
return;
}
pid = g_waitchild();
if (pid > 0)
{
#ifdef OLDSESSION
for (i = 0; i < 100; i++)
{
if (g_session_items[i].pid == pid)
{
g_memset(g_session_items + i, 0, sizeof(struct session_item));
g_session_count--;
}
}
#else
session_kill(pid);
#endif
}
}
extern int thread_sck;
/******************************************************************************/
/**
@ -104,7 +65,10 @@ sesman_main_loop()
while (in_sck > 0)
{
/* we've got a connection, so we pass it to scp code */
scp_process_start(in_sck);
LOG_DBG("new connection",0);
thread_sck=in_sck;
//scp_process_start((void*)in_sck);
thread_scp_start(in_sck);
/* once we've processed the connection, we go back listening */
in_sck = g_tcp_accept(g_sck);
@ -260,17 +224,23 @@ main(int argc, char** argv)
g_file_open("/dev/null");
g_file_open("/dev/null");
}
/* initializing locks */
lock_init();
/* signal handling */
#ifdef OLDSESSION
g_memset(&g_session_items, 0, sizeof(g_session_items));
#endif
g_pid = g_getpid();
g_signal(1, sig_sesman_reload_cfg); /* SIGHUP */
g_signal(2, sig_sesman_shutdown); /* SIGINT */
g_signal(9, sig_sesman_shutdown); /* SIGKILL */
g_signal(15, sig_sesman_shutdown); /* SIGTERM */
g_signal_child_stop(cterm); /* SIGCHLD */
/* old style signal handling is now managed synchronously by a
* separate thread. uncomment this block if you need old style
* signal handling and comment out thread_sighandler_start() */
/*
g_signal(1, sig_sesman_reload_cfg); / * SIGHUP * /
g_signal(2, sig_sesman_shutdown); / * SIGINT * /
g_signal(9, sig_sesman_shutdown); / * SIGKILL * /
g_signal(15, sig_sesman_shutdown); / * SIGTERM * /
g_signal_child_stop(cterm); / * SIGCHLD * /
*/
thread_sighandler_start();
/* writing pid file */
fd = g_file_open(SESMAN_PID_FILE);

@ -41,6 +41,8 @@
#include "session.h"
#include "access.h"
#include "scp.h"
#include "thread.h"
#include "lock.h"
#ifndef SESMAN_PID_FILE
#define SESMAN_PID_FILE "./sesman.pid"

@ -29,35 +29,18 @@
extern unsigned char g_fixedkey[8];
extern struct config_sesman g_cfg; /* config.h */
//extern int g_server_type;
#ifdef OLDSESSION
extern struct session_item g_session_items[100]; /* sesman.h */
#else
struct session_chain* g_sessions;
#endif
int g_session_count;
/******************************************************************************/
struct session_item* DEFAULT_CC
session_get_bydata(char* name, int width, int height, int bpp)
{
#ifdef OLDSESSION
int i;
for (i = 0; i < 100; i++)
{
if (g_strncmp(name, g_session_items[i].name, 255) == 0 &&
g_session_items[i].width == width &&
g_session_items[i].height == height &&
g_session_items[i].bpp == bpp)
{
return g_session_items + i;
}
}
#else
struct session_chain* tmp;
/*THREAD-FIX require chain lock */
lock_chain_acquire();
tmp=g_sessions;
while (tmp != 0)
@ -68,13 +51,14 @@ session_get_bydata(char* name, int width, int height, int bpp)
tmp->item->bpp == bpp)
{
/*THREAD-FIX release chain lock */
lock_chain_release();
return tmp->item;
}
tmp=tmp->next;
}
/*THREAD-FIX release chain lock */
#endif
lock_chain_release();
return 0;
}
@ -139,20 +123,23 @@ session_start(int width, int height, int bpp, char* username, char* password,
char cur_dir[256];
char text[256];
char passwd_file[256];
#ifndef OLDSESSION
struct session_chain* temp;
#endif
/*THREAD-FIX lock to control g_session_count*/
lock_chain_acquire();
/* check to limit concurrent sessions */
if (g_session_count >= g_cfg.sess.max_sessions)
{
/*THREAD-FIX unlock chain*/
lock_chain_release();
log_message(LOG_LEVEL_INFO, "max concurrent session limit exceeded. login \
for user %s denied", username);
return 0;
}
#ifndef OLDSESSION
/*THREAD-FIX unlock chain*/
lock_chain_release();
temp = (struct session_chain*)g_malloc(sizeof(struct session_chain), 0);
if (temp == 0)
{
@ -168,13 +155,15 @@ for user %s denied", username);
username);
return 0;
}
#endif
g_get_current_dir(cur_dir, 255);
display = 10;
/*while (x_server_running(display) && display < 50)*/
/* we search for a free display up to max_sessions */
/* we should need no more displays than this */
/* block all the threads running to enable forking */
lock_fork_request();
while (x_server_running(display))
{
display++;
@ -256,7 +245,7 @@ for user %s denied", username);
g_exit(1);
}
/* should not get here */
log_message(LOG_LEVEL_ALWAYS,"error doing execve for user %s - pid %d",
log_message(LOG_LEVEL_ALWAYS,"error doing execve (%s) for user %s - pid %d",
username, g_getpid());
g_exit(1);
}
@ -273,32 +262,9 @@ for user %s denied", username);
}
else /* parent */
{
#ifdef OLDSESSION
g_session_items[display].pid = pid;
g_strcpy(g_session_items[display].name, username);
g_session_items[display].display = display;
g_session_items[display].width = width;
g_session_items[display].height = height;
g_session_items[display].bpp = bpp;
g_session_items[display].data = data;
g_session_items[display].connect_time=g_time1();
g_session_items[display].disconnect_time=(time_t) 0;
g_session_items[display].idle_time=(time_t) 0;
i/*if (type==0)
{
g_session_items[display].type=SESMAN_SESSION_TYPE_XVNC;
}
else
{
g_session_items[display].type=SESMAN_SESSION_TYPE_XRDP;
}*/
g_session_items[display].type = type;
g_session_items[display].status = SESMAN_SESSION_STATUS_ACTIVE;
g_session_count++;
#else
/* let the other threads go on */
lock_fork_release();
temp->item->pid = pid;
temp->item->display = display;
temp->item->width = width;
@ -311,24 +277,17 @@ for user %s denied", username);
temp->item->disconnect_time = 0;
temp->item->idle_time = 0;
/* if (type==0)
{
temp->item->type=SESMAN_SESSION_TYPE_XVNC;
}
else
{
temp->item->type=SESMAN_SESSION_TYPE_XRDP;
}*/
temp->item->type=type;
temp->item->status=SESMAN_SESSION_STATUS_ACTIVE;
/*THREAD-FIX lock the chain*/
/*THREAD-FIX lock the chain*/
lock_chain_acquire();
temp->next=g_sessions;
g_sessions=temp;
g_session_count++;
/*THERAD-FIX free the chain*/
#endif
lock_chain_release();
g_sleep(5000);
}
return display;
@ -371,8 +330,6 @@ struct session_chain
};
*/
#ifndef OLDSESSION
/******************************************************************************/
int DEFAULT_CC
session_kill(int pid)
@ -381,6 +338,8 @@ session_kill(int pid)
struct session_chain* prev;
/*THREAD-FIX require chain lock */
lock_chain_acquire();
tmp=g_sessions;
prev=0;
@ -401,6 +360,7 @@ session_kill(int pid)
prev->next = tmp->next;
}
/*THREAD-FIX release chain lock */
lock_chain_release();
return SESMAN_SESSION_KILL_NULLITEM;
}
@ -423,6 +383,7 @@ session_kill(int pid)
g_free(tmp);
g_session_count--;
/*THREAD-FIX release chain lock */
lock_chain_release();
return SESMAN_SESSION_KILL_OK;
}
@ -432,6 +393,7 @@ session_kill(int pid)
}
/*THREAD-FIX release chain lock */
lock_chain_release();
return SESMAN_SESSION_KILL_NOTFOUND;
}
@ -441,7 +403,9 @@ session_get_bypid(int pid)
{
struct session_chain* tmp;
/*THREAD-FIX require chain lock */
/*THREAD-FIX require chain lock */
lock_chain_acquire();
tmp = g_sessions;
while (tmp != 0)
{
@ -450,12 +414,14 @@ session_get_bypid(int pid)
log_message(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!",
pid);
/*THREAD-FIX release chain lock */
lock_chain_release();
return 0;
}
if (tmp->item->pid == pid)
{
/*THREAD-FIX release chain lock */
lock_chain_release();
return tmp->item;
}
@ -464,8 +430,7 @@ session_get_bypid(int pid)
}
/*THREAD-FIX release chain lock */
lock_chain_release();
return 0;
}
#endif

@ -27,6 +27,8 @@
#include "sesman.h"
#include "signal.h"
extern int g_sck;
extern int g_pid;
extern struct config_sesman g_cfg;
@ -73,3 +75,78 @@ sig_sesman_reload_cfg(int sig)
log_message(LOG_LEVEL_INFO, "configuration reloaded");
}
/******************************************************************************/
void DEFAULT_CC
sig_sesman_session_end(int sig)
{
int pid;
if (g_getpid() != g_pid)
{
return;
}
pid = g_waitchild();
if (pid > 0)
{
session_kill(pid);
}
}
/******************************************************************************/
void* DEFAULT_CC
sig_handler_thread(void* arg)
{
int recv_signal;
sigset_t sigmask;
sigset_t oldmask;
sigset_t waitmask;
/* mask signals to be able to wait for them... */
sigfillset(&sigmask);
/* it is a good idea not to block SIGILL SIGSEGV */
/* SIGFPE -- see sigaction(2) NOTES */
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
/* building the signal wait mask... */
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGHUP);
sigaddset(&waitmask, SIGCHLD);
sigaddset(&waitmask, SIGTERM);
// sigaddset(&waitmask, SIGFPE);
// sigaddset(&waitmask, SIGILL);
// sigaddset(&waitmask, SIGSEGV);
do
{
LOG_DBG("calling sigwait()",0);
sigwait(&waitmask, &recv_signal);
switch (recv_signal)
{
case SIGHUP:
//reload cfg
LOG_DBG("sesman received SIGHUP",0);
//return 0;
break;
case SIGCHLD:
/* a session died */
LOG_DBG("sesman received SIGCHLD",0);
sig_sesman_session_end(SIGCHLD);
break;
/*case SIGKILL;
/* we die * /
LOG_DBG("sesman received SIGKILL",0);
sig_sesman_shutdown(recv_signal);
break;*/
case SIGTERM:
/* we die */
LOG_DBG("sesman received SIGTERM",0);
sig_sesman_shutdown(recv_signal);
break;
}
} while (1);
return 0;
}

@ -46,5 +46,22 @@ sig_sesman_shutdown(int sig);
void DEFAULT_CC
sig_sesman_reload_cfg(int sig);
/**
*
* @brief SIGCHLD handling code
* @param sig The received signal
*
*/
void DEFAULT_CC
sig_sesman_session_end(int sig);
/**
*
* @brief signal handling thread
*
*/
void* DEFAULT_CC
sig_handler_thread(void* arg);
#endif

@ -32,6 +32,9 @@ int DEFAULT_CC
tcp_force_recv(int sck, char* data, int len)
{
int rcvd;
int block;
block = lock_fork_critical_section_start();
while (len > 0)
{
@ -57,6 +60,9 @@ tcp_force_recv(int sck, char* data, int len)
len -= rcvd;
}
}
lock_fork_critical_section_end(block);
return 0;
}
@ -65,7 +71,10 @@ int DEFAULT_CC
tcp_force_send(int sck, char* data, int len)
{
int sent;
int block;
block = lock_fork_critical_section_start();
while (len > 0)
{
sent = g_tcp_send(sck, data, len, 0);
@ -90,6 +99,9 @@ tcp_force_send(int sck, char* data, int len)
len -= sent;
}
}
lock_fork_critical_section_end(block);
return 0;
}

@ -0,0 +1,173 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2006
*/
/**
*
* @file thread.c
* @brief thread stuff...
* @author Simone Fedele
*
*/
#include "sesman.h"
#include <errno.h>
#include <signal.h>
#include <pthread.h>
static pthread_t thread_sighandler;
//static pthread_t thread_updater;
/* a variable to pass the socket of s connection to a thread */
int thread_sck;
/******************************************************************************/
int DEFAULT_CC
thread_sighandler_start()
{
int ret;
sigset_t sigmask;
sigset_t oldmask;
sigset_t waitmask;
/* mask signals to be able to wait for them... */
sigfillset(&sigmask);
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
/* unblock some signals... */
sigemptyset(&waitmask);
/* it is a good idea not to block SIGILL SIGSEGV */
/* SIGFPE -- see sigaction(2) NOTES */
sigaddset(&waitmask, SIGILL);
sigaddset(&waitmask, SIGSEGV);
sigaddset(&waitmask, SIGFPE);
pthread_sigmask(SIG_UNBLOCK, &waitmask, NULL);
log_message(LOG_LEVEL_INFO,"starting signal handling thread...");
ret = pthread_create(&thread_sighandler, NULL, sig_handler_thread, "");
pthread_detach(thread_sighandler);
if (ret==0)
{
log_message(LOG_LEVEL_INFO, "signal handler thread started successfully");
return 0;
}
/* if something happened while starting a new thread... */
switch (ret)
{
case EINVAL:
log_message(LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)");
break;
case EAGAIN:
log_message(LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)");
break;
case EPERM:
log_message(LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)");
break;
default:
log_message(LOG_LEVEL_ERROR, "unknown error starting signal handling thread");
}
return 1;
}
#ifdef JUST_TO_AVOID_COMPILER_ERRORS
/******************************************************************************/
int DEFAULT_CC
thread_session_update_start()
{
int ret;
//starts the session update thread
//that checks for idle time, destroys sessions, ecc...
#warning this thread should always request lock_fork before read or write
#warning (so we can Fork() In Peace)
ret = pthread_create(&thread_updater, NULL, , "");
pthread_detach(thread_updater);
if (ret==0)
{
log_message(LOG_LEVEL_INFO, "session update thread started successfully");
return 0;
}
/* if something happened while starting a new thread... */
switch (ret)
{
case EINVAL:
log_message(LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)");
break;
case EAGAIN:
log_message(LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)");
break;
case EPERM:
log_message(LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)");
break;
default:
log_message(LOG_LEVEL_ERROR, "unknown error starting session update thread");
}
return 1;
}
#endif
/******************************************************************************/
int DEFAULT_CC
thread_scp_start(int skt)
{
int ret;
pthread_t th;
/* blocking the use of thread_skt */
lock_socket_acquire();
thread_sck=skt;
/* start a thread that processes a connection */
ret = pthread_create(&th, NULL, scp_process_start, "");
//ret = pthread_create(&th, NULL, scp_process_start, (void*) (&thread_sck));
pthread_detach(th);
if (ret==0)
{
log_message(LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt);
return 0;
}
/* if something happened while starting a new thread... */
switch (ret)
{
case EINVAL:
log_message(LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt);
break;
case EAGAIN:
log_message(LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt);
break;
case EPERM:
log_message(LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt);
break;
default:
log_message(LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d");
}
return 1;
}

@ -0,0 +1,57 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2006
*/
/**
*
* @file thread.h
* @brief thread stuff...
* @author Simone Fedele
*
*/
#ifndef THREAD_H
#define THREAD_H
/**
*
* @brief Starts the signal handling thread
* @retval 0 on success
* @retval 1 on error
*
*/
int DEFAULT_CC
thread_sighandler_start();
/**
*
* @brief Starts the session update thread
*
*/
int DEFAULT_CC
thread_session_update_start();
/**
*
* @brief Starts a thread to handle an incoming connection
*
*/
int DEFAULT_CC
thread_scp_start();
#endif
Loading…
Cancel
Save