diff -ur stunnel-4.03/src/prototypes.h stunnel-4.03a/src/prototypes.h --- stunnel-4.03/src/prototypes.h 2002-10-20 14:04:30.000000000 -0400 +++ stunnel-4.03a/src/prototypes.h 2002-12-20 09:32:40.000000000 -0500 @@ -33,7 +33,7 @@ void log_error_addr(int, int, struct sockaddr_in *, char *); int set_socket_options(int, int); #ifndef USE_WIN32 -void local_handler(int); +void sigchld_handler(int); #endif char *stunnel_info(void); int alloc_fd(int); @@ -73,9 +73,16 @@ CRIT_SECTIONS } section_code; +#ifdef USE_FORK +/* If we are forking, let the compiler factor out these calls */ +#define enter_critical_section(i) (void)0 +#define leave_critical_section(i) (void)0 +#define sthreads_init() (void)0 +#else void enter_critical_section(section_code); void leave_critical_section(section_code); void sthreads_init(void); +#endif unsigned long process_id(void); unsigned long thread_id(void); int create_client(int, int, void *, void *(*)(void *)); diff -ur stunnel-4.03/src/sthreads.c stunnel-4.03a/src/sthreads.c --- stunnel-4.03/src/sthreads.c 2002-10-24 06:13:43.000000000 -0400 +++ stunnel-4.03a/src/sthreads.c 2002-12-20 09:32:40.000000000 -0500 @@ -162,18 +162,6 @@ #ifdef USE_FORK -void enter_critical_section(section_code i) { - /* empty */ -} - -void leave_critical_section(section_code i) { - /* empty */ -} - -void sthreads_init(void) { - /* empty */ -} - unsigned long process_id(void) { return (unsigned long)getpid(); } @@ -193,7 +181,7 @@ case 0: /* child */ if(ls>=0) closesocket(ls); - signal(SIGCHLD, local_handler); + signal(SIGCHLD, sigchld_handler); cli(arg); exit(0); default: /* parent */ diff -ur stunnel-4.03/src/stunnel.c stunnel-4.03a/src/stunnel.c --- stunnel-4.03/src/stunnel.c 2002-10-24 06:25:03.000000000 -0400 +++ stunnel-4.03a/src/stunnel.c 2002-12-20 10:07:40.000000000 -0500 @@ -56,20 +56,25 @@ /* Error/exceptions handling functions */ static char *my_strerror(int); -#ifdef USE_FORK -static void sigchld_handler(int); -#endif #ifndef USE_WIN32 +void sigchld_handler(int); +static void child_exit(void); static void signal_handler(int); #endif int num_clients=0; /* Current number of clients */ - +static volatile int child_flag=0; /* Child Signal Handler flag */ + /* Functions */ #ifndef USE_WIN32 int main(int argc, char* argv[]) { /* execution begins here 8-) */ + /* The umask is being set to 077 in case we core dump. */ +#if defined( S_IRWXG ) && defined( S_IRWXO ) + umask(S_IRWXG | S_IRWXO); +#endif + main_initialize(argc>1 ? argv[1] : NULL); signal(SIGPIPE, SIG_IGN); /* avoid 'broken pipe' signal */ @@ -120,6 +125,10 @@ #endif num_clients=1; client(alloc_client_session(&local_options, 0, 1)); +#ifndef USE_WIN32 + if(child_flag) + child_exit(); +#endif } /* close SSL */ context_free(); /* free global SSL context */ @@ -185,14 +194,10 @@ #if !defined (USE_WIN32) && !defined (__vms) if(!(options.option.foreground)) daemonize(); -#ifdef USE_FORK +#ifndef USE_WIN32 /* handle signals about dead children */ signal(SIGCHLD, sigchld_handler); -#endif /* defined USE_FORK */ -#ifdef USE_PTHREAD - /* handle signals about dead local processes */ - signal(SIGCHLD, local_handler); -#endif /* defined USE_PTHREAD */ +#endif /* defined USE_WIN32 */ drop_privileges(); create_pid(); #endif /* !defined USE_WIN32 && !defined (__vms) */ @@ -213,10 +218,19 @@ err=get_last_socket_error(); if(err!=EINTR) log_error(LOG_ERR, err, "select"); /* non-critical error */ - } else - for(opt=local_options.next; opt; opt=opt->next) +#ifndef USE_WIN32 + if(child_flag) + child_exit(); +#endif + } else + for(opt=local_options.next; opt; opt=opt->next) { +#ifndef USE_WIN32 + if(child_flag) + child_exit(); +#endif if(FD_ISSET(opt->fd, ¤t_set)) accept_connection(opt); + } } log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)"); } @@ -590,59 +604,38 @@ } } -#ifdef USE_FORK -static void sigchld_handler(int sig) { /* dead children detected */ - int pid, status; +#ifndef USE_WIN32 -#ifdef HAVE_WAIT_FOR_PID - while((pid=wait_for_pid(-1, &status, WNOHANG))>0) { - num_clients--; /* one client less */ -#else - if((pid=wait(&status))>0) { - num_clients--; /* one client less */ -#endif -#ifdef WIFSIGNALED - if(WIFSIGNALED(status)) { - log(LOG_DEBUG, "Process %d terminated on signal %d (%d left)", - pid, WTERMSIG(status), num_clients); - } else { - log(LOG_DEBUG, "Process %d finished with code %d (%d left)", - pid, WEXITSTATUS(status), num_clients); - } - } -#else - log(LOG_DEBUG, "Process %d finished with code %d (%d left)", - pid, status, num_clients); - } -#endif +void sigchld_handler(int sig) { /* death of process detected */ + child_flag = 1; signal(SIGCHLD, sigchld_handler); } -#endif - -#ifndef USE_WIN32 -void local_handler(int sig) { /* dead of local (-l) process detected */ - int pid, status; +static void child_exit(void) { + int pid, status, num_left; + child_flag = 0; #ifdef HAVE_WAIT_FOR_PID while((pid=wait_for_pid(-1, &status, WNOHANG))>0) { #else if((pid=wait(&status))>0) { #endif + enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */ + num_left = --num_clients; /* one client less */ + leave_critical_section(CRIT_CLIENTS); #ifdef WIFSIGNALED if(WIFSIGNALED(status)) { - log(LOG_DEBUG, "Local process %d terminated on signal %d", - pid, WTERMSIG(status)); + log(LOG_DEBUG, "Process %d terminated on signal %d (%d left)", + pid, WTERMSIG(status), num_left); } else { - log(LOG_DEBUG, "Local process %d finished with code %d", - pid, WEXITSTATUS(status)); + log(LOG_DEBUG, "Process %d finished with code %d (%d left)", + pid, WEXITSTATUS(status), num_left); } #else - log(LOG_DEBUG, "Local process %d finished with status %d", - pid, status); + log(LOG_DEBUG, "Process %d finished with code %d (%d left)", + pid, status, num_left); #endif } - signal(SIGCHLD, local_handler); } static void signal_handler(int sig) { /* signal handler */