1 --- stunnel-3.22/client.c 2001-12-23 14:41:32.000000000 -0500
2 +++ stunnel-3.22/client.c 2003-04-10 14:52:18.000000000 -0400
4 if(!options.foreground)
7 + signal(SIGCHLD, SIG_DFL);
9 putenv("LD_PRELOAD=" libdir "/stunnel.so");
10 /* For Tru64 _RLD_LIST is used instead */
11 --- stunnel-3.22/stunnel.c 2001-12-20 02:53:54.000000000 -0500
12 +++ stunnel-3.22/stunnel.c 2003-04-10 15:06:33.000000000 -0400
14 void sockerror(char *);
15 void log_error(int, int, char *);
16 static char *my_strerror(int);
17 +static void child_exited_handler(int, int);
19 static void sigchld_handler(int);
24 server_options options;
30 sthreads_init(); /* initialize threads */
31 log(LOG_NOTICE, "%s", stunnel_info());
32 if(options.option & OPT_DAEMON) { /* daemon mode */
33 + if(pipe(signal_pipe)) {
38 if(!(options.option & OPT_FOREGROUND))
41 struct sockaddr_in addr;
43 int max_clients, fds_ulimit=-1;
48 #if defined HAVE_SYSCONF
49 fds_ulimit=sysconf(_SC_OPEN_MAX);
51 log(LOG_ERR, "Memory allocation failed");
54 - max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-6)/2;
55 + max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-8)/2;
56 log(LOG_NOTICE, "FD_SETSIZE=%d, file ulimit=%d%s -> %d clients allowed",
57 FD_SETSIZE, fds_ulimit, fds_ulimit<0?" (unlimited)":"", max_clients);
63 - s=accept(ls, (struct sockaddr *)&addr, &addrlen);
64 - } while(s<0 && get_last_socket_error()==EINTR);
66 + FD_SET(ls, &read_fds);
67 + FD_SET(signal_pipe[0], &read_fds);
68 + ready=select((ls > signal_pipe[0]) ? ls + 1 : signal_pipe[0] + 1,
69 + &read_fds, NULL, NULL, NULL);
70 + } while(ready<=0 && get_last_error()==EINTR);
71 + /* reap a child which exited, decrementing the client count if we forked it */
72 + if(FD_ISSET(signal_pipe[0], &read_fds)) {
73 + read(signal_pipe[0], &c, 1);
75 + child_exited_handler(1, 0); /* decrement the client count */
77 + child_exited_handler(0, 1); /* the parent thread already decremented
81 + /* if we didn't also have a new connection, go back to waiting */
82 + if(!FD_ISSET(ls, &read_fds)) {
85 + /* if we also have a new connection, process it */
86 + s=accept(ls, (struct sockaddr *)&addr, &addrlen);
95 -static void sigchld_handler(int sig) { /* Dead children detected */
96 +static void child_exited_handler(int consume_client, int local) { /* Dead children detected */
99 #ifdef HAVE_WAIT_FOR_PID
100 while((pid=wait_for_pid(-1, &status, WNOHANG))>0) {
101 - options.clients--; /* One client less */
103 if((pid=wait(&status))>0) {
104 - options.clients--; /* One client less */
106 + if(consume_client) {
107 + enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */
108 + options.clients--; /* One client less */
109 + leave_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */
112 if(WIFSIGNALED(status)) {
113 - log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)",
114 - options.servname, pid, WTERMSIG(status), options.clients);
116 + log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d",
117 + options.servname, pid, WTERMSIG(status));
119 + log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)",
120 + options.servname, pid, WTERMSIG(status), options.clients);
122 - log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
123 - options.servname, pid, WEXITSTATUS(status), options.clients);
125 + log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d",
126 + options.servname, pid, WEXITSTATUS(status));
128 + log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
129 + options.servname, pid, WEXITSTATUS(status),
134 - log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
135 - options.servname, pid, status, options.clients);
137 + log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d",
138 + options.servname, pid, status);
140 + log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)",
141 + options.servname, pid, status, options.clients);
147 +static void sigchld_handler(int sig) { /* Dead children detected */
148 + write(signal_pipe[1], "", 1);
149 signal(SIGCHLD, sigchld_handler);
155 void local_handler(int sig) { /* Dead of local (-l) process detected */
158 -#ifdef HAVE_WAIT_FOR_PID
159 - while((pid=wait_for_pid(-1, &status, WNOHANG))>0) {
161 - if((pid=wait(&status))>0) {
164 - if(WIFSIGNALED(status)) {
165 - log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d",
166 - options.servname, pid, WTERMSIG(status));
168 - log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d",
169 - options.servname, pid, WEXITSTATUS(status));
172 - log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d",
173 - options.servname, pid, status);
176 + write(signal_pipe[1], "", 1);
177 signal(SIGCHLD, local_handler);
180 --- stunnel-3.22/sthreads.c 2001-11-11 10:06:22.000000000 -0500
181 +++ stunnel-3.22/sthreads.c 2003-04-10 14:52:18.000000000 -0400
186 +extern int signal_pipe[2];
187 +static void null_handler(int signum) {
188 + signal(SIGCHLD, null_handler);
191 int create_client(int ls, int s, void *(*cli)(void *)) {
198 - signal(SIGCHLD, local_handler);
199 + signal(SIGCHLD, null_handler);
200 + close(signal_pipe[0]);
201 + close(signal_pipe[1]);
204 default: /* parent */