2 Unix SMB/CIFS implementation.
4 process model: standard (1 process per client connection)
6 Copyright (C) Andrew Tridgell 1992-2005
7 Copyright (C) James J Myers 2003 <myersjj@samba.org>
8 Copyright (C) Stefan (metze) Metzmacher 2004
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.
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.
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/>.
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"
31 #include "lib/messaging/messaging.h"
32 #include "lib/util/debug.h"
33 #include "source3/lib/messages_dgm.h"
35 struct standard_child_state {
40 struct tevent_fd *from_child_fde;
43 NTSTATUS process_model_standard_init(TALLOC_CTX *);
45 static int from_parent_fd;
48 called when the process model is selected
50 static void standard_model_init(void)
54 static void sighup_signal_handler(struct tevent_context *ev,
55 struct tevent_signal *se,
56 int signum, int count, void *siginfo,
59 debug_schedule_reopen_logs();
62 static void sigterm_signal_handler(struct tevent_context *ev,
63 struct tevent_signal *se,
64 int signum, int count, void *siginfo,
68 if (getpgrp() == getpid()) {
70 * We're the process group leader, send
71 * SIGTERM to our process group.
73 DEBUG(0,("SIGTERM: killing children\n"));
74 kill(-getpgrp(), SIGTERM);
77 DEBUG(0,("Exiting pid %u on SIGTERM\n", (unsigned int)getpid()));
83 handle EOF on the parent-to-all-children pipe in the child
85 static void standard_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde,
86 uint16_t flags, void *private_data)
88 DEBUG(10,("Child %d exiting\n", (int)getpid()));
89 talloc_free(event_ctx);
94 handle EOF on the child pipe in the parent, so we know when a
95 process terminates without using SIGCHLD or waiting on all possible pids.
97 We need to ensure we do not ignore SIGCHLD because we need it to
98 work to get a valid error code from samba_runcmd_*().
100 static void standard_child_pipe_handler(struct tevent_context *ev,
101 struct tevent_fd *fde,
105 struct standard_child_state *state
106 = talloc_get_type_abort(private_data, struct standard_child_state);
110 messaging_dgm_cleanup(state->pid);
112 /* the child has closed the pipe, assume its dead */
114 pid = waitpid(state->pid, &status, 0);
116 if (pid != state->pid) {
117 if (errno == ECHILD) {
119 * this happens when the
120 * parent has set SIGCHLD to
121 * SIG_IGN. In that case we
123 * information for the child
124 * via its logging. We should
125 * stop using SIG_IGN on
126 * SIGCHLD in the standard
129 DEBUG(0, ("Error in waitpid() unexpectedly got ECHILD "
130 "for child %d (%s) - %s, someone has set SIGCHLD "
132 (int)state->pid, state->name,
137 DEBUG(0, ("Error in waitpid() for child %d (%s) - %s \n",
138 (int)state->pid, state->name, strerror(errno)));
145 if (WIFEXITED(status)) {
146 status = WEXITSTATUS(status);
147 DEBUG(2, ("Child %d (%s) exited with status %d\n",
148 (int)state->pid, state->name, status));
149 } else if (WIFSIGNALED(status)) {
150 status = WTERMSIG(status);
151 DEBUG(0, ("Child %d (%s) terminated with signal %d\n",
152 (int)state->pid, state->name, status));
158 static struct standard_child_state *setup_standard_child_pipe(struct tevent_context *ev,
161 struct standard_child_state *state;
162 int parent_child_pipe[2];
166 * Prepare a pipe to allow us to know when the child exits,
167 * because it will trigger a read event on this private
170 * We do all this before the accept and fork(), so we can
171 * clean up if it fails.
173 state = talloc_zero(ev, struct standard_child_state);
182 state->name = talloc_strdup(state, name);
183 if (state->name == NULL) {
188 ret = pipe(parent_child_pipe);
190 DEBUG(0, ("Failed to create parent-child pipe to handle "
191 "SIGCHLD to track new process for socket\n"));
196 smb_set_close_on_exec(parent_child_pipe[0]);
197 smb_set_close_on_exec(parent_child_pipe[1]);
199 state->from_child_fd = parent_child_pipe[0];
200 state->to_parent_fd = parent_child_pipe[1];
203 * The basic purpose of calling this handler is to ensure we
204 * call waitpid() and so avoid zombies (now that we no longer
205 * user SIGIGN on for SIGCHLD), but it also allows us to clean
206 * up other resources in the future.
208 state->from_child_fde = tevent_add_fd(ev, state,
209 state->from_child_fd,
211 standard_child_pipe_handler,
213 if (state->from_child_fde == NULL) {
217 tevent_fd_set_auto_close(state->from_child_fde);
223 called when a listening socket becomes readable.
225 static void standard_accept_connection(struct tevent_context *ev,
226 struct loadparm_context *lp_ctx,
227 struct socket_context *sock,
228 void (*new_conn)(struct tevent_context *,
229 struct loadparm_context *, struct socket_context *,
230 struct server_id , void *),
234 struct socket_context *sock2;
236 struct socket_address *c, *s;
237 struct standard_child_state *state;
238 struct tevent_fd *fde = NULL;
239 struct tevent_signal *se = NULL;
241 state = setup_standard_child_pipe(ev, NULL);
246 /* accept an incoming connection. */
247 status = socket_accept(sock, &sock2);
248 if (!NT_STATUS_IS_OK(status)) {
249 DEBUG(0,("standard_accept_connection: accept: %s\n",
251 /* this looks strange, but is correct. We need to throttle things until
252 the system clears enough resources to handle this new socket */
254 close(state->to_parent_fd);
255 state->to_parent_fd = -1;
263 close(state->to_parent_fd);
264 state->to_parent_fd = -1;
272 /* parent or error code ... */
274 /* go back to the event loop */
278 /* this leaves state->to_parent_fd open */
283 /* This is now the child code. We need a completely new event_context to work with */
285 if (tevent_re_initialise(ev) != 0) {
286 smb_panic("Failed to re-initialise tevent after fork");
289 /* this will free all the listening sockets and all state that
290 is not associated with this new connection */
293 /* we don't care if the dup fails, as its only a select()
294 speed optimisation */
297 /* tdb needs special fork handling */
298 ldb_wrap_fork_hook();
300 /* Must be done after a fork() to reset messaging contexts. */
301 status = imessaging_reinit_all();
302 if (!NT_STATUS_IS_OK(status)) {
303 smb_panic("Failed to re-initialise imessaging after fork");
306 fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ,
307 standard_pipe_handler, NULL);
309 smb_panic("Failed to add fd handler after fork");
312 se = tevent_add_signal(ev,
316 sighup_signal_handler,
319 smb_panic("Failed to add SIGHUP handler after fork");
322 se = tevent_add_signal(ev,
326 sigterm_signal_handler,
329 smb_panic("Failed to add SIGTERM handler after fork");
332 /* setup the process title */
333 c = socket_get_peer_addr(sock2, ev);
334 s = socket_get_my_addr(sock2, ev);
336 setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
337 c->addr, c->port, s->addr, s->port, (int)pid);
342 /* setup this new connection. Cluster ID is PID based for this process model */
343 new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);
345 /* we can't return to the top level here, as that event context is gone,
346 so we now process events in the new event context until there are no
348 tevent_loop_wait(ev);
355 called to create a new server task
357 static void standard_new_task(struct tevent_context *ev,
358 struct loadparm_context *lp_ctx,
359 const char *service_name,
360 void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
362 int new_from_parent_fd)
366 struct standard_child_state *state;
367 struct tevent_fd *fde = NULL;
368 struct tevent_signal *se = NULL;
370 state = setup_standard_child_pipe(ev, service_name);
374 from_parent_fd = new_from_parent_fd;
379 close(state->to_parent_fd);
380 state->to_parent_fd = -1;
388 /* parent or error code ... go back to the event loop */
392 /* this leaves state->to_parent_fd open */
397 /* this will free all the listening sockets and all state that
398 is not associated with this new connection */
399 if (tevent_re_initialise(ev) != 0) {
400 smb_panic("Failed to re-initialise tevent after fork");
403 /* ldb/tdb need special fork handling */
404 ldb_wrap_fork_hook();
406 /* Must be done after a fork() to reset messaging contexts. */
407 status = imessaging_reinit_all();
408 if (!NT_STATUS_IS_OK(status)) {
409 smb_panic("Failed to re-initialise imessaging after fork");
412 fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ,
413 standard_pipe_handler, NULL);
415 smb_panic("Failed to add fd handler after fork");
418 se = tevent_add_signal(ev,
422 sighup_signal_handler,
425 smb_panic("Failed to add SIGHUP handler after fork");
428 se = tevent_add_signal(ev,
432 sigterm_signal_handler,
435 smb_panic("Failed to add SIGTERM handler after fork");
438 setproctitle("task %s server_id[%d]", service_name, (int)pid);
440 /* setup this new task. Cluster ID is PID based for this process model */
441 new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);
443 /* we can't return to the top level here, as that event context is gone,
444 so we now process events in the new event context until there are no
446 tevent_loop_wait(ev);
453 /* called when a task goes down */
454 _NORETURN_ static void standard_terminate(struct tevent_context *ev, struct loadparm_context *lp_ctx,
457 DEBUG(2,("standard_terminate: reason[%s]\n",reason));
459 /* this reload_charcnv() has the effect of freeing the iconv context memory,
460 which makes leak checking easier */
461 reload_charcnv(lp_ctx);
463 /* Always free event context last before exit. */
466 /* terminate this process */
470 /* called to set a title of a task or connection */
471 static void standard_set_title(struct tevent_context *ev, const char *title)
474 setproctitle("%s", title);
480 static const struct model_ops standard_ops = {
482 .model_init = standard_model_init,
483 .accept_connection = standard_accept_connection,
484 .new_task = standard_new_task,
485 .terminate = standard_terminate,
486 .set_title = standard_set_title,
490 initialise the standard process model, registering ourselves with the process model subsystem
492 NTSTATUS process_model_standard_init(TALLOC_CTX *ctx)
494 return register_process_model(&standard_ops);