parent
20e26f1ccd
commit
fda836169e
@ -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
|
@ -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…
Reference in new issue