s4: process_standard: Add a simplified SIGTERM handler based on code from source4...
[sfrench/samba-autobuild/.git] / source4 / smbd / process_standard.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    process model: standard (1 process per client connection)
5
6    Copyright (C) Andrew Tridgell 1992-2005
7    Copyright (C) James J Myers 2003 <myersjj@samba.org>
8    Copyright (C) Stefan (metze) Metzmacher 2004
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "lib/events/events.h"
26 #include "smbd/process_model.h"
27 #include "system/filesys.h"
28 #include "cluster/cluster.h"
29 #include "param/param.h"
30 #include "ldb_wrap.h"
31 #include "lib/messaging/messaging.h"
32 #include "lib/util/debug.h"
33
34 struct standard_child_state {
35         const char *name;
36         pid_t pid;
37         int to_parent_fd;
38         int from_child_fd;
39         struct tevent_fd *from_child_fde;
40 };
41
42 NTSTATUS process_model_standard_init(void);
43
44 /* we hold a pipe open in the parent, and the any child
45    processes wait for EOF on that pipe. This ensures that
46    children die when the parent dies */
47 static int child_pipe[2] = { -1, -1 };
48
49 /*
50   called when the process model is selected
51 */
52 static void standard_model_init(void)
53 {
54         int rc;
55
56         rc = pipe(child_pipe);
57         if (rc < 0) {
58                 smb_panic("Failed to initialize pipe!");
59         }
60 }
61
62 static void sighup_signal_handler(struct tevent_context *ev,
63                                 struct tevent_signal *se,
64                                 int signum, int count, void *siginfo,
65                                 void *private_data)
66 {
67         debug_schedule_reopen_logs();
68 }
69
70 static void sigterm_signal_handler(struct tevent_context *ev,
71                                 struct tevent_signal *se,
72                                 int signum, int count, void *siginfo,
73                                 void *private_data)
74 {
75 #if HAVE_GETPGRP
76         if (getpgrp() == getpid()) {
77                 /*
78                  * We're the process group leader, send
79                  * SIGTERM to our process group.
80                  */
81                 DEBUG(0,("SIGTERM: killing children\n"));
82                 kill(-getpgrp(), SIGTERM);
83         }
84 #endif
85         DEBUG(0,("Exiting pid %u on SIGTERM\n", (unsigned int)getpid()));
86         talloc_free(ev);
87         exit(127);
88 }
89
90 /*
91   handle EOF on the parent-to-all-children pipe in the child
92 */
93 static void standard_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde, 
94                                   uint16_t flags, void *private_data)
95 {
96         DEBUG(10,("Child %d exiting\n", (int)getpid()));
97         talloc_free(event_ctx);
98         exit(0);
99 }
100
101 /*
102   handle EOF on the child pipe in the parent, so we know when a
103   process terminates without using SIGCHLD or waiting on all possible pids.
104
105   We need to ensure we do not ignore SIGCHLD because we need it to
106   work to get a valid error code from samba_runcmd_*().
107  */
108 static void standard_child_pipe_handler(struct tevent_context *ev,
109                                         struct tevent_fd *fde,
110                                         uint16_t flags,
111                                         void *private_data)
112 {
113         struct standard_child_state *state
114                 = talloc_get_type_abort(private_data, struct standard_child_state);
115         int status = 0;
116         pid_t pid;
117
118         /* the child has closed the pipe, assume its dead */
119         errno = 0;
120         pid = waitpid(state->pid, &status, 0);
121
122         if (pid != state->pid) {
123                 if (errno == ECHILD) {
124                         /*
125                          * this happens when the
126                          * parent has set SIGCHLD to
127                          * SIG_IGN. In that case we
128                          * can only get error
129                          * information for the child
130                          * via its logging. We should
131                          * stop using SIG_IGN on
132                          * SIGCHLD in the standard
133                          * process model.
134                          */
135                         DEBUG(0, ("Error in waitpid() unexpectedly got ECHILD "
136                                   "for child %d (%s) - %s, someone has set SIGCHLD "
137                                   "to SIG_IGN!\n",
138                                   (int)state->pid, state->name,
139                                   strerror(errno)));
140                         TALLOC_FREE(state);
141                         return;
142                 }
143                 DEBUG(0, ("Error in waitpid() for child %d (%s) - %s \n",
144                           (int)state->pid, state->name, strerror(errno)));
145                 if (errno == 0) {
146                         errno = ECHILD;
147                 }
148                 TALLOC_FREE(state);
149                 return;
150         }
151         if (WIFEXITED(status)) {
152                 status = WEXITSTATUS(status);
153                 DEBUG(2, ("Child %d (%s) exited with status %d\n",
154                           (int)state->pid, state->name, status));
155         } else if (WIFSIGNALED(status)) {
156                 status = WTERMSIG(status);
157                 DEBUG(0, ("Child %d (%s) terminated with signal %d\n",
158                           (int)state->pid, state->name, status));
159         }
160         TALLOC_FREE(state);
161         return;
162 }
163
164 static struct standard_child_state *setup_standard_child_pipe(struct tevent_context *ev,
165                                                               const char *name)
166 {
167         struct standard_child_state *state;
168         int parent_child_pipe[2];
169         int ret;
170
171         /*
172          * Prepare a pipe to allow us to know when the child exits,
173          * because it will trigger a read event on this private
174          * pipe.
175          *
176          * We do all this before the accept and fork(), so we can
177          * clean up if it fails.
178          */
179         state = talloc_zero(ev, struct standard_child_state);
180         if (state == NULL) {
181                 return NULL;
182         }
183
184         if (name == NULL) {
185                 name = "";
186         }
187
188         state->name = talloc_strdup(state, name);
189         if (state->name == NULL) {
190                 TALLOC_FREE(state);
191                 return NULL;
192         }
193
194         ret = pipe(parent_child_pipe);
195         if (ret == -1) {
196                 DEBUG(0, ("Failed to create parent-child pipe to handle "
197                           "SIGCHLD to track new process for socket\n"));
198                 TALLOC_FREE(state);
199                 return NULL;
200         }
201
202         smb_set_close_on_exec(parent_child_pipe[0]);
203         smb_set_close_on_exec(parent_child_pipe[1]);
204
205         state->from_child_fd = parent_child_pipe[0];
206         state->to_parent_fd = parent_child_pipe[1];
207
208         /*
209          * The basic purpose of calling this handler is to ensure we
210          * call waitpid() and so avoid zombies (now that we no longer
211          * user SIGIGN on for SIGCHLD), but it also allows us to clean
212          * up other resources in the future.
213          */
214         state->from_child_fde = tevent_add_fd(ev, state,
215                                               state->from_child_fd,
216                                               TEVENT_FD_READ,
217                                               standard_child_pipe_handler,
218                                               state);
219         if (state->from_child_fde == NULL) {
220                 TALLOC_FREE(state);
221                 return NULL;
222         }
223         tevent_fd_set_auto_close(state->from_child_fde);
224
225         return state;
226 }
227
228 /*
229   called when a listening socket becomes readable. 
230 */
231 static void standard_accept_connection(struct tevent_context *ev, 
232                                        struct loadparm_context *lp_ctx,
233                                        struct socket_context *sock, 
234                                        void (*new_conn)(struct tevent_context *,
235                                                         struct loadparm_context *, struct socket_context *, 
236                                                         struct server_id , void *), 
237                                        void *private_data)
238 {
239         NTSTATUS status;
240         struct socket_context *sock2;
241         pid_t pid;
242         struct socket_address *c, *s;
243         struct standard_child_state *state;
244         struct tevent_fd *fde = NULL;
245         struct tevent_signal *se = NULL;
246
247         state = setup_standard_child_pipe(ev, NULL);
248         if (state == NULL) {
249                 return;
250         }
251
252         /* accept an incoming connection. */
253         status = socket_accept(sock, &sock2);
254         if (!NT_STATUS_IS_OK(status)) {
255                 DEBUG(0,("standard_accept_connection: accept: %s\n",
256                          nt_errstr(status)));
257                 /* this looks strange, but is correct. We need to throttle things until
258                    the system clears enough resources to handle this new socket */
259                 sleep(1);
260                 close(state->to_parent_fd);
261                 state->to_parent_fd = -1;
262                 TALLOC_FREE(state);
263                 return;
264         }
265
266         pid = fork();
267
268         if (pid != 0) {
269                 close(state->to_parent_fd);
270                 state->to_parent_fd = -1;
271
272                 if (pid > 0) {
273                         state->pid = pid;
274                 } else {
275                         TALLOC_FREE(state);
276                 }
277
278                 /* parent or error code ... */
279                 talloc_free(sock2);
280                 /* go back to the event loop */
281                 return;
282         }
283
284         /* this leaves state->to_parent_fd open */
285         TALLOC_FREE(state);
286
287         pid = getpid();
288
289         /* This is now the child code. We need a completely new event_context to work with */
290
291         if (tevent_re_initialise(ev) != 0) {
292                 smb_panic("Failed to re-initialise tevent after fork");
293         }
294
295         /* this will free all the listening sockets and all state that
296            is not associated with this new connection */
297         talloc_free(sock);
298
299         /* we don't care if the dup fails, as its only a select()
300            speed optimisation */
301         socket_dup(sock2);
302                         
303         /* tdb needs special fork handling */
304         ldb_wrap_fork_hook();
305
306         /* Must be done after a fork() to reset messaging contexts. */
307         status = imessaging_reinit_all();
308         if (!NT_STATUS_IS_OK(status)) {
309                 smb_panic("Failed to re-initialise imessaging after fork");
310         }
311
312         fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
313                       standard_pipe_handler, NULL);
314         if (fde == NULL) {
315                 smb_panic("Failed to add fd handler after fork");
316         }
317
318         if (child_pipe[1] != -1) {
319                 close(child_pipe[1]);
320                 child_pipe[1] = -1;
321         }
322
323         se = tevent_add_signal(ev,
324                                 ev,
325                                 SIGHUP,
326                                 0,
327                                 sighup_signal_handler,
328                                 NULL);
329         if (se == NULL) {
330                 smb_panic("Failed to add SIGHUP handler after fork");
331         }
332
333         se = tevent_add_signal(ev,
334                                 ev,
335                                 SIGTERM,
336                                 0,
337                                 sigterm_signal_handler,
338                                 NULL);
339         if (se == NULL) {
340                 smb_panic("Failed to add SIGTERM handler after fork");
341         }
342
343         /* setup the process title */
344         c = socket_get_peer_addr(sock2, ev);
345         s = socket_get_my_addr(sock2, ev);
346         if (s && c) {
347                 setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
348                              c->addr, c->port, s->addr, s->port, (int)pid);
349         }
350         talloc_free(c);
351         talloc_free(s);
352
353         /* setup this new connection.  Cluster ID is PID based for this process model */
354         new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);
355
356         /* we can't return to the top level here, as that event context is gone,
357            so we now process events in the new event context until there are no
358            more to process */      
359         tevent_loop_wait(ev);
360
361         talloc_free(ev);
362         exit(0);
363 }
364
365 /*
366   called to create a new server task
367 */
368 static void standard_new_task(struct tevent_context *ev, 
369                               struct loadparm_context *lp_ctx,
370                               const char *service_name,
371                               void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
372                               void *private_data)
373 {
374         pid_t pid;
375         NTSTATUS status;
376         struct standard_child_state *state;
377         struct tevent_fd *fde = NULL;
378         struct tevent_signal *se = NULL;
379
380         state = setup_standard_child_pipe(ev, service_name);
381         if (state == NULL) {
382                 return;
383         }
384
385         pid = fork();
386
387         if (pid != 0) {
388                 close(state->to_parent_fd);
389                 state->to_parent_fd = -1;
390
391                 if (pid > 0) {
392                         state->pid = pid;
393                 } else {
394                         TALLOC_FREE(state);
395                 }
396
397                 /* parent or error code ... go back to the event loop */
398                 return;
399         }
400
401         /* this leaves state->to_parent_fd open */
402         TALLOC_FREE(state);
403
404         pid = getpid();
405
406         /* this will free all the listening sockets and all state that
407            is not associated with this new connection */
408         if (tevent_re_initialise(ev) != 0) {
409                 smb_panic("Failed to re-initialise tevent after fork");
410         }
411
412         /* ldb/tdb need special fork handling */
413         ldb_wrap_fork_hook();
414
415         /* Must be done after a fork() to reset messaging contexts. */
416         status = imessaging_reinit_all();
417         if (!NT_STATUS_IS_OK(status)) {
418                 smb_panic("Failed to re-initialise imessaging after fork");
419         }
420
421         fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
422                       standard_pipe_handler, NULL);
423         if (fde == NULL) {
424                 smb_panic("Failed to add fd handler after fork");
425         }
426         if (child_pipe[1] != -1) {
427                 close(child_pipe[1]);
428                 child_pipe[1] = -1;
429         }
430
431         se = tevent_add_signal(ev,
432                                 ev,
433                                 SIGHUP,
434                                 0,
435                                 sighup_signal_handler,
436                                 NULL);
437         if (se == NULL) {
438                 smb_panic("Failed to add SIGHUP handler after fork");
439         }
440
441         se = tevent_add_signal(ev,
442                                 ev,
443                                 SIGTERM,
444                                 0,
445                                 sigterm_signal_handler,
446                                 NULL);
447         if (se == NULL) {
448                 smb_panic("Failed to add SIGTERM handler after fork");
449         }
450
451         setproctitle("task %s server_id[%d]", service_name, (int)pid);
452
453         /* setup this new task.  Cluster ID is PID based for this process model */
454         new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);
455
456         /* we can't return to the top level here, as that event context is gone,
457            so we now process events in the new event context until there are no
458            more to process */      
459         tevent_loop_wait(ev);
460
461         talloc_free(ev);
462         exit(0);
463 }
464
465
466 /* called when a task goes down */
467 _NORETURN_ static void standard_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx,
468                                           const char *reason) 
469 {
470         DEBUG(2,("standard_terminate: reason[%s]\n",reason));
471
472         /* this reload_charcnv() has the effect of freeing the iconv context memory,
473            which makes leak checking easier */
474         reload_charcnv(lp_ctx);
475
476         /* Always free event context last before exit. */
477         talloc_free(ev);
478
479         /* terminate this process */
480         exit(0);
481 }
482
483 /* called to set a title of a task or connection */
484 static void standard_set_title(struct tevent_context *ev, const char *title) 
485 {
486         if (title) {
487                 setproctitle("%s", title);
488         } else {
489                 setproctitle(NULL);
490         }
491 }
492
493 static const struct model_ops standard_ops = {
494         .name                   = "standard",
495         .model_init             = standard_model_init,
496         .accept_connection      = standard_accept_connection,
497         .new_task               = standard_new_task,
498         .terminate              = standard_terminate,
499         .set_title              = standard_set_title,
500 };
501
502 /*
503   initialise the standard process model, registering ourselves with the process model subsystem
504  */
505 NTSTATUS process_model_standard_init(void)
506 {
507         return register_process_model(&standard_ops);
508 }