]>
Commit | Line | Data |
---|---|---|
1711f127 | 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 | |
3 | @@ -711,6 +711,7 @@ | |
4 | if(!options.foreground) | |
5 | dup2(fd[1], 2); | |
6 | closesocket(fd[1]); | |
7 | + signal(SIGCHLD, SIG_DFL); | |
8 | if(c->ip) { | |
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 | |
13 | @@ -63,6 +63,7 @@ | |
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); | |
18 | #ifdef USE_FORK | |
19 | static void sigchld_handler(int); | |
20 | #endif | |
21 | @@ -74,6 +75,7 @@ | |
22 | #endif | |
23 | ||
24 | server_options options; | |
25 | +int signal_pipe[2]; | |
26 | ||
27 | #ifdef USE_WIN32 | |
28 | /* | |
29 | @@ -138,6 +140,10 @@ | |
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)) { | |
34 | + ioerror("pipe"); | |
35 | + exit(1); | |
36 | + } | |
37 | #ifndef USE_WIN32 | |
38 | if(!(options.option & OPT_FOREGROUND)) | |
39 | daemonize(); | |
40 | @@ -165,6 +171,9 @@ | |
41 | struct sockaddr_in addr; | |
42 | int addrlen; | |
43 | int max_clients, fds_ulimit=-1; | |
44 | + int ready; | |
45 | + char c; | |
46 | + fd_set read_fds; | |
47 | ||
48 | #if defined HAVE_SYSCONF | |
49 | fds_ulimit=sysconf(_SC_OPEN_MAX); | |
50 | @@ -188,7 +197,7 @@ | |
51 | log(LOG_ERR, "Memory allocation failed"); | |
52 | exit(1); | |
53 | } | |
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); | |
58 | ls=listen_local(); | |
59 | @@ -204,8 +213,28 @@ | |
60 | while(1) { | |
61 | addrlen=sizeof(addr); | |
62 | do { | |
63 | - s=accept(ls, (struct sockaddr *)&addr, &addrlen); | |
64 | - } while(s<0 && get_last_socket_error()==EINTR); | |
65 | + FD_ZERO(&read_fds); | |
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); | |
74 | +#ifdef USE_FORK | |
75 | + child_exited_handler(1, 0); /* decrement the client count */ | |
76 | +#else | |
77 | + child_exited_handler(0, 1); /* the parent thread already decremented | |
78 | + the client count */ | |
79 | +#endif | |
80 | + } | |
81 | + /* if we didn't also have a new connection, go back to waiting */ | |
82 | + if(!FD_ISSET(ls, &read_fds)) { | |
83 | + continue; | |
84 | + } | |
85 | + /* if we also have a new connection, process it */ | |
86 | + s=accept(ls, (struct sockaddr *)&addr, &addrlen); | |
87 | if(s<0) { | |
88 | sockerror("accept"); | |
89 | continue; | |
90 | @@ -574,31 +603,51 @@ | |
91 | } | |
92 | } | |
93 | ||
94 | -#ifdef USE_FORK | |
95 | -static void sigchld_handler(int sig) { /* Dead children detected */ | |
96 | +static void child_exited_handler(int consume_client, int local) { /* Dead children detected */ | |
97 | int pid, status; | |
98 | ||
99 | #ifdef HAVE_WAIT_FOR_PID | |
100 | while((pid=wait_for_pid(-1, &status, WNOHANG))>0) { | |
101 | - options.clients--; /* One client less */ | |
102 | #else | |
103 | if((pid=wait(&status))>0) { | |
104 | - options.clients--; /* One client less */ | |
105 | #endif | |
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 */ | |
110 | + } | |
111 | #ifdef WIFSIGNALED | |
112 | if(WIFSIGNALED(status)) { | |
113 | - log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)", | |
114 | - options.servname, pid, WTERMSIG(status), options.clients); | |
115 | + if(local) | |
116 | + log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d", | |
117 | + options.servname, pid, WTERMSIG(status)); | |
118 | + else | |
119 | + log(LOG_DEBUG, "%s[%d] terminated on signal %d (%d left)", | |
120 | + options.servname, pid, WTERMSIG(status), options.clients); | |
121 | } else { | |
122 | - log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)", | |
123 | - options.servname, pid, WEXITSTATUS(status), options.clients); | |
124 | + if(local) | |
125 | + log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d", | |
126 | + options.servname, pid, WEXITSTATUS(status)); | |
127 | + else | |
128 | + log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)", | |
129 | + options.servname, pid, WEXITSTATUS(status), | |
130 | + options.clients); | |
131 | } | |
132 | } | |
133 | #else | |
134 | - log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)", | |
135 | - options.servname, pid, status, options.clients); | |
136 | + if(local) | |
137 | + log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d", | |
138 | + options.servname, pid, status); | |
139 | + else | |
140 | + log(LOG_DEBUG, "%s[%d] finished with code %d (%d left)", | |
141 | + options.servname, pid, status, options.clients); | |
142 | } | |
143 | #endif | |
144 | +} | |
145 | + | |
146 | +#ifdef USE_FORK | |
147 | +static void sigchld_handler(int sig) { /* Dead children detected */ | |
148 | + write(signal_pipe[1], "", 1); | |
149 | signal(SIGCHLD, sigchld_handler); | |
150 | } | |
151 | #endif | |
152 | @@ -606,26 +655,7 @@ | |
153 | #ifndef USE_WIN32 | |
154 | ||
155 | void local_handler(int sig) { /* Dead of local (-l) process detected */ | |
156 | - int pid, status; | |
157 | - | |
158 | -#ifdef HAVE_WAIT_FOR_PID | |
159 | - while((pid=wait_for_pid(-1, &status, WNOHANG))>0) { | |
160 | -#else | |
161 | - if((pid=wait(&status))>0) { | |
162 | -#endif | |
163 | -#ifdef WIFSIGNALED | |
164 | - if(WIFSIGNALED(status)) { | |
165 | - log(LOG_DEBUG, "Local process %s (PID=%lu) terminated on signal %d", | |
166 | - options.servname, pid, WTERMSIG(status)); | |
167 | - } else { | |
168 | - log(LOG_DEBUG, "Local process %s (PID=%lu) finished with code %d", | |
169 | - options.servname, pid, WEXITSTATUS(status)); | |
170 | - } | |
171 | -#else | |
172 | - log(LOG_DEBUG, "Local process %s (PID=%lu) finished with status %d", | |
173 | - options.servname, pid, status); | |
174 | -#endif | |
175 | - } | |
176 | + write(signal_pipe[1], "", 1); | |
177 | signal(SIGCHLD, local_handler); | |
178 | } | |
179 | ||
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 | |
182 | @@ -180,6 +180,11 @@ | |
183 | return 0L; | |
184 | } | |
185 | ||
186 | +extern int signal_pipe[2]; | |
187 | +static void null_handler(int signum) { | |
188 | + signal(SIGCHLD, null_handler); | |
189 | +} | |
190 | + | |
191 | int create_client(int ls, int s, void *(*cli)(void *)) { | |
192 | switch(fork()) { | |
193 | case -1: /* error */ | |
194 | @@ -187,7 +192,9 @@ | |
195 | return -1; | |
196 | case 0: /* child */ | |
197 | closesocket(ls); | |
198 | - signal(SIGCHLD, local_handler); | |
199 | + signal(SIGCHLD, null_handler); | |
200 | + close(signal_pipe[0]); | |
201 | + close(signal_pipe[1]); | |
202 | cli((void *)s); | |
203 | exit(0); | |
204 | default: /* parent */ |