1 /*
2 * exitproc.c -- Actions to perform on exit()
3 *
4 * exitproc.c is a part of binkd project
5 *
6 * Copyright (C) 1997 Dima Maloff, 5047/13
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. See COPYING.
12 */
13
14 /*
15 * $Id: exitproc.c,v 2.44.2.1 2014/08/09 15:17:42 gul Exp $
16 *
17 * $Log: exitproc.c,v $
18 * Revision 2.44.2.1 2014/08/09 15:17:42 gul
19 * Large files support on Win32 (backport from develop branch)
20 *
21 * Revision 2.44 2012/01/03 17:25:31 green
22 * Implemented IPv6 support
23 * - replace (almost) all getXbyY function calls with getaddrinfo/getnameinfo (RFC2553) calls
24 * - Add compatibility layer for target systems not supporting RFC2553 calls in rfc2553.[ch]
25 * - Add support for multiple listen sockets -- one for IPv4 and one for IPv6 (use V6ONLY)
26 * - For WIN32 platform add configuration parameter IPV6 (mutually exclusive with BINKD9X)
27 * - On WIN32 platform use Winsock2 API if IPV6 support is requested
28 * - config: node IP address literal + port supported: [<ipv6 address>]:<port>
29 *
30 * Revision 2.43 2010/05/24 14:24:32 gul
31 * Exit immediately after all jobs done in "-p" mode
32 *
33 * Revision 2.42 2009/06/02 17:09:35 gul
34 * Build binkd for OS/2 with perl support
35 *
36 * Revision 2.41 2009/05/31 07:16:16 gul
37 * Warning: many changes, may be unstable.
38 * Perl interpreter is now part of config and rerun on config reload.
39 * Perl 5.10 compatibility.
40 * Changes in outbound queue managing and sorting.
41 *
42 * Revision 2.40 2004/10/18 15:22:19 gul
43 * Change handle perl errors method
44 *
45 * Revision 2.39 2004/02/07 14:06:06 hbrew
46 * Macros: RTLDLL-->RTLSTATIC, BINKDW9X-->BINKD9X
47 *
48 * Revision 2.38 2004/01/03 19:04:20 stas
49 * New functions: public w32Init() and hidden w32exitfunc()
50 *
51 * Revision 2.37 2004/01/03 12:17:43 stas
52 * Implement full icon support (winNT/2k/XP)
53 *
54 * Revision 2.36 2003/10/29 21:08:38 gul
55 * Change include-files structure, relax dependences
56 *
57 * Revision 2.35 2003/10/28 13:09:53 gul
58 * Fix NT service semaphore usage in exitfunc()
59 *
60 * Revision 2.34 2003/10/18 06:45:23 stas
61 * Fix a semaphore usage in exitfunc()
62 *
63 * Revision 2.33 2003/10/17 18:49:36 stas
64 * Use a semaphore to prevent double run exitfunc()
65 *
66 * Revision 2.32 2003/10/13 08:48:09 stas
67 * Implement true NT service stop sequence
68 *
69 * Revision 2.31 2003/10/08 10:30:34 gul
70 * Fixed debug logging (thx to Alexander Reznikov)
71 *
72 * Revision 2.30 2003/10/07 20:50:07 gul
73 * Wait for servmanager exit from exitproc()
74 * (Patch from Alexander Reznikov)
75 *
76 * Revision 2.29 2003/10/07 17:57:09 gul
77 * Some small changes in close threads function.
78 * Inhibit errors "socket operation on non-socket" on break.
79 *
80 * Revision 2.28 2003/09/11 13:04:13 hbrew
81 * Undo 'move binkd9x deinit to exitfunc()' patch
82 *
83 * Revision 2.27 2003/09/09 17:57:43 stream
84 * Do not unload config on exit (considered useless and potentially unstable)
85 *
86 * Revision 2.26 2003/09/08 08:21:20 stream
87 * Cleanup config semaphore, free memory of base config on exit.
88 *
89 * Revision 2.25 2003/09/08 06:36:51 val
90 * (a) don't call exitfunc for perlhook fork'ed process
91 * (b) many compilation warnings in perlhooks.c fixed
92 *
93 * Revision 2.24 2003/09/07 04:49:41 hbrew
94 * Remove binkd9x restart-on-config-change code; move binkd9x deinit to exitfunc()
95 *
96 * Revision 2.23 2003/08/26 22:18:47 gul
97 * Fix compilation under w32-mingw and os2-emx
98 *
99 * Revision 2.22 2003/08/26 16:06:26 stream
100 * Reload configuration on-the fly.
101 *
102 * Warning! Lot of code can be broken (Perl for sure).
103 * Compilation checked only under OS/2-Watcom and NT-MSVC (without Perl)
104 *
105 * Revision 2.21 2003/08/17 10:38:55 gul
106 * Return semaphoring for log and binlog
107 *
108 * Revision 2.20 2003/08/16 09:08:33 gul
109 * Binlog semaphoring removed
110 *
111 * Revision 2.19 2003/08/16 06:21:12 gul
112 * Log() semaphoring removed
113 *
114 * Revision 2.18 2003/08/14 12:56:29 gul
115 * Make Log() thread-safe
116 *
117 * Revision 2.17 2003/08/14 11:43:19 val
118 * free allocated log buffer in exitfunc()
119 *
120 * Revision 2.16 2003/06/20 10:37:02 val
121 * Perl hooks for binkd - initial revision
122 *
123 * Revision 2.15 2003/06/04 10:36:58 stas
124 * Thread-safety tcperr() implementation on Win32
125 *
126 * Revision 2.14 2003/06/02 08:26:00 gul
127 * Fix hang on exit with big loglevel
128 *
129 * Revision 2.13 2003/05/04 08:45:30 gul
130 * Lock semaphores more safely for resolve and IP-addr print
131 *
132 * Revision 2.12 2003/03/31 19:53:08 gul
133 * Close socket before exit
134 *
135 * Revision 2.11 2003/03/31 19:35:16 gul
136 * Clean semaphores usage
137 *
138 * Revision 2.10 2003/03/11 11:42:23 gul
139 * Use event semaphores for exit threads
140 *
141 * Revision 2.9 2003/03/11 09:21:30 gul
142 * Fixed OS/2 Watcom compilation
143 *
144 * Revision 2.8 2003/03/10 10:39:23 gul
145 * New include file common.h
146 *
147 * Revision 2.7 2003/03/10 08:38:07 gul
148 * Make n_servers/n_clients changes thread-safe
149 *
150 * Revision 2.6 2003/03/09 18:19:32 gul
151 * Bugfix
152 *
153 * Revision 2.5 2003/03/06 18:30:28 gul
154 * A bit optimize
155 *
156 * Revision 2.4 2003/03/05 11:43:56 gul
157 * Fix win32 compilation
158 *
159 * Revision 2.3 2003/03/05 11:40:12 gul
160 * Fix win32 compilation
161 *
162 * Revision 2.2 2003/03/05 09:00:45 gul
163 * Fix win32 compilation
164 *
165 * Revision 2.1 2003/03/03 23:41:20 gul
166 * Try to resolve problem with active threads while exitproc running
167 *
168 * Revision 2.0 2001/01/10 12:12:37 gul
169 * Binkd is under CVS again
170 *
171 * Revision 1.2 1997/10/23 04:13:35 mff
172 * pidfiles are now killed only by servmgrs, misc
173 *
174 * Revision 1.1 1997/08/12 21:42:54 mff
175 * Initial revision
176 */
177
178 #include <signal.h>
179
180 #include "sys.h"
181 #include "readcfg.h"
182 #include "common.h"
183 #include "ftnnode.h"
184 #include "bsy.h"
185 #include "tools.h"
186 #include "sem.h"
187 #include "server.h"
188 #ifdef WITH_PERL
189 #include "perlhooks.h"
190 #endif
191 #ifdef BINKD9X
192 #include "nt/win9x.h"
193 #endif
194 #if defined(WIN32) && !defined(BINKD9X)
195 #include "nt/service.h"
196 #include "nt/w32tools.h"
197 #endif
198
199 int binkd_exit;
200
201 #ifdef HAVE_THREADS
202
203 static fd_set sockets;
204 static SOCKET max_socket;
205
add_socket(SOCKET sockfd)206 int add_socket(SOCKET sockfd)
207 {
208 threadsafe(
209 FD_SET (sockfd, &sockets);
210 if (sockfd >= max_socket)
211 max_socket = sockfd + 1;
212 );
213 return 0;
214 }
215
del_socket(SOCKET sockfd)216 int del_socket(SOCKET sockfd)
217 {
218 threadsafe(FD_CLR (sockfd, &sockets));
219 return 0;
220 }
221
222 #endif
223
close_srvmgr_socket(void)224 void close_srvmgr_socket(void)
225 {
226 int curfd;
227
228 for (curfd=0; curfd<sockfd_used; curfd++)
229 { Log (5, "Closing server socket # %i", sockfd[curfd]);
230 soclose (sockfd[curfd]);
231 }
232 sockfd_used = 0;
233 }
234
exitfunc(void)235 void exitfunc (void)
236 {
237 BINKD_CONFIG *config;
238 #if defined(WIN32) && !defined(BINKD9X)
239 static int exitfunc_called_flag=0;
240
241 if (IsNT() && isService()) {
242 LockSem(&exitsem);
243 if(exitfunc_called_flag)
244 { /* prevent double call exitfunc() at NT service stop sequence */
245 ReleaseSem(&exitsem);
246 Log(10, "exitfunc() repeated call, return from exitfunc()");
247 return;
248 }
249 exitfunc_called_flag=1;
250 ReleaseSem(&exitsem);
251 }
252 #endif
253
254 Log(7, "exitfunc()");
255
256 #ifdef HAVE_FORK
257 if (pidcmgr)
258 { int i;
259 i=pidcmgr, pidcmgr=0; /* prevent abort when cmgr exits */
260 kill (i, SIGTERM);
261 /* sleep (1); */
262 }
263 close_srvmgr_socket();
264 #elif defined(HAVE_THREADS)
265 /* exit all threads */
266 { SOCKET h;
267 int timeout = 0;
268 /* wait for threads exit */
269 binkd_exit = 1;
270 for (;;)
271 #ifdef OS2
272 if (n_servers || n_clients || (pidcmgr && server_flag))
273 #else
274 if (n_servers || n_clients || pidcmgr || pidsmgr)
275 #endif
276 {
277 close_srvmgr_socket();
278 if (pidcmgr)
279 PostSem(&wakecmgr);
280 /* close active sockets */
281 for (h=0; h < max_socket; h++)
282 if (FD_ISSET(h, &sockets))
283 soclose (h);
284
285 if (WaitSem (&eothread, 1))
286 {
287 timeout++;
288 if (timeout == 4) /* 4 sec */
289 {
290 Log(5, "exitfunc(): warning, threads exit timeout (%i sec)!", timeout);
291 break;
292 }
293 }
294 else
295 timeout = 0;
296 }
297 else
298 {
299 Log(8, "exitfunc(): all threads finished");
300 break;
301 }
302 }
303 #endif
304
305 config = lock_current_config();
306 if (config)
307 bsy_remove_all (config);
308 sock_deinit ();
309 nodes_deinit ();
310 if (config)
311 {
312 if (*config->pid_file && pidsmgr == (int) getpid ())
313 delete (config->pid_file);
314 /* completely unload config */
315 #ifdef HAVE_FORK
316 unlock_config_structure(config, inetd_flag || (!pidsmgr && pidCmgr == (int) getpid()) || (pidsmgr == (int) getpid()));
317 #else
318 unlock_config_structure(config, 1);
319 #endif
320 }
321 CleanSem (&config_sem);
322 CleanSem (&hostsem);
323 CleanSem (&resolvsem);
324 CleanSem (&lsem);
325 CleanSem (&blsem);
326 CleanSem (&varsem);
327 CleanEventSem (&eothread);
328 CleanEventSem (&wakecmgr);
329 #ifdef OS2
330 CleanSem (&fhsem);
331 #endif
332 #if defined(WITH_PERL) && defined(HAVE_THREADS) && defined(PERL_MULTITHREAD)
333 CleanSem (&perlsem);
334 #endif
335 ReleaseErrorList();
336 }
337