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