--- /dev/null
+--- stunnel-3.22/client.c 2001-12-23 14:41:32.000000000 -0500
++++ stunnel-3.22/client.c 2003-04-10 14:52:18.000000000 -0400
+@@ -711,6 +711,7 @@
+ if(!options.foreground)
+ dup2(fd[1], 2);
+ closesocket(fd[1]);
++ signal(SIGCHLD, SIG_DFL);
+ if(c->ip) {
+ putenv("LD_PRELOAD=" libdir "/stunnel.so");
+ /* For Tru64 _RLD_LIST is used instead */
+--- stunnel-3.22/stunnel.c 2001-12-20 02:53:54.000000000 -0500
++++ stunnel-3.22/stunnel.c 2003-04-10 15:06:33.000000000 -0400
+@@ -63,6 +63,7 @@
+ void sockerror(char *);
+ void log_error(int, int, char *);
+ static char *my_strerror(int);
++static void child_exited_handler(int, int);
+ #ifdef USE_FORK
+ static void sigchld_handler(int);
+ #endif
+@@ -74,6 +75,7 @@
+ #endif
+
+ server_options options;
++int signal_pipe[2];
+
+ #ifdef USE_WIN32
+ /*
+@@ -138,6 +140,10 @@
+ sthreads_init(); /* initialize threads */
+ log(LOG_NOTICE, "%s", stunnel_info());
+ if(options.option & OPT_DAEMON) { /* daemon mode */
++ if(pipe(signal_pipe)) {
++ ioerror("pipe");
++ exit(1);
++ }
+ #ifndef USE_WIN32
+ if(!(options.option & OPT_FOREGROUND))
+ daemonize();
+@@ -165,6 +171,9 @@
+ struct sockaddr_in addr;
+ int addrlen;
+ int max_clients, fds_ulimit=-1;
++ int ready;
++ char c;
++ fd_set read_fds;
+
+ #if defined HAVE_SYSCONF
+ fds_ulimit=sysconf(_SC_OPEN_MAX);
+@@ -188,7 +197,7 @@
+ log(LOG_ERR, "Memory allocation failed");
+ exit(1);
+ }
+- max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-6)/2;
++ max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-8)/2;
+ log(LOG_NOTICE, "FD_SETSIZE=%d, file ulimit=%d%s -> %d clients allowed",
+ FD_SETSIZE, fds_ulimit, fds_ulimit<0?" (unlimited)":"", max_clients);
+ ls=listen_local();
+@@ -204,8 +213,28 @@
+ while(1) {
+ addrlen=sizeof(addr);
+ do {
+- s=accept(ls, (struct sockaddr *)&addr, &addrlen);
+- } while(s<0 && get_last_socket_error()==EINTR);
++ FD_ZERO(&read_fds);
++ FD_SET(ls, &read_fds);
++ FD_SET(signal_pipe[0], &read_fds);
++ ready=select((ls > signal_pipe[0]) ? ls + 1 : signal_pipe[0] + 1,
++ &read_fds, NULL, NULL, NULL);
++ } while(ready<=0 && get_last_error()==EINTR);
++ /* reap a child which exited, decrementing the client count if we forked it */
++ if(FD_ISSET(signal_pipe[0], &read_fds)) {
++ read(signal_pipe[0], &c, 1);
++#ifdef USE_FORK
++ child_exited_handler(1, 0); /* decrement the client count */
++#else
++ child_exited_handler(0, 1); /* the parent thread already decremented
++ the client count */
++#endif
++ }
++ /* if we didn't also have a new connection, go back to waiting */
++ if(!FD_ISSET(ls, &read_fds)) {
++ continue;
++ }
++ /* if we also have a new connection, process it */
++ s=accept(ls, (struct sockaddr *)&addr, &addrlen);
+ if(s<0) {
+ sockerror("accept");
+ continue;
+@@ -574,31 +603,51 @@
+ }
+ }
+
+-#ifdef USE_FORK
+-static void sigchld_handler(int sig) { /* Dead children detected */
++static void child_exited_handler(int consume_client, int local) { /* Dead children detected */
+ int pid, status;
+
+ #ifdef HAVE_WAIT_FOR_PID
+ while((pid=wait_for_pid(-1, &status, WNOHANG))>0) {
+- options.clients--; /* One client less */
+ #else
+ if((pid=wait(&status))>0) {
+- options.clients--; /* One client less */
+ #endif
++ if(consume_client) {
++ enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */
++ options.clients--; /* One client less */
++ leave_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */
++ }
+ #ifdef WIFSIGNALED
+ if(WIFSIGNALED(status)) {
+- log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)",
+- options.servname, pid, WTERMSIG(status), options.clients);
++ if(local)
++ log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d",
++ options.servname, pid, WTERMSIG(status));
++ else
++ log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)",
++ options.servname, pid, WTERMSIG(status), options.clients);
+ } else {
+- log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
+- options.servname, pid, WEXITSTATUS(status), options.clients);
++ if(local)
++ log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d",
++ options.servname, pid, WEXITSTATUS(status));
++ else
++ log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
++ options.servname, pid, WEXITSTATUS(status),
++ options.clients);
+ }
+ }
+ #else
+- log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
+- options.servname, pid, status, options.clients);
++ if(local)
++ log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d",
++ options.servname, pid, status);
++ else
++ log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
++ options.servname, pid, status, options.clients);
+ }
+ #endif
++}
++
++#ifdef USE_FORK
++static void sigchld_handler(int sig) { /* Dead children detected */
++ write(signal_pipe[1], "", 1);
+ signal(SIGCHLD, sigchld_handler);
+ }
+ #endif
+@@ -606,26 +655,7 @@
+ #ifndef USE_WIN32
+
+ void local_handler(int sig) { /* Dead of local (-l) process detected */
+- int pid, status;
+-
+-#ifdef HAVE_WAIT_FOR_PID
+- while((pid=wait_for_pid(-1, &status, WNOHANG))>0) {
+-#else
+- if((pid=wait(&status))>0) {
+-#endif
+-#ifdef WIFSIGNALED
+- if(WIFSIGNALED(status)) {
+- log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d",
+- options.servname, pid, WTERMSIG(status));
+- } else {
+- log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d",
+- options.servname, pid, WEXITSTATUS(status));
+- }
+-#else
+- log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d",
+- options.servname, pid, status);
+-#endif
+- }
++ write(signal_pipe[1], "", 1);
+ signal(SIGCHLD, local_handler);
+ }
+
+--- stunnel-3.22/sthreads.c 2001-11-11 10:06:22.000000000 -0500
++++ stunnel-3.22/sthreads.c 2003-04-10 14:52:18.000000000 -0400
+@@ -180,6 +180,11 @@
+ return 0L;
+ }
+
++extern int signal_pipe[2];
++static void null_handler(int signum) {
++ signal(SIGCHLD, null_handler);
++}
++
+ int create_client(int ls, int s, void *(*cli)(void *)) {
+ switch(fork()) {
+ case -1: /* error */
+@@ -187,7 +192,9 @@
+ return -1;
+ case 0: /* child */
+ closesocket(ls);
+- signal(SIGCHLD, local_handler);
++ signal(SIGCHLD, null_handler);
++ close(signal_pipe[0]);
++ close(signal_pipe[1]);
+ cli((void *)s);
+ exit(0);
+ default: /* parent */