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 *);
44 struct process_context {
47 bool inhibit_fork_on_accept;
48 bool forked_on_accept;
52 called when the process model is selected
54 static void standard_model_init(void)
58 static void sighup_signal_handler(struct tevent_context *ev,
59 struct tevent_signal *se,
60 int signum, int count, void *siginfo,
63 debug_schedule_reopen_logs();
66 static void sigterm_signal_handler(struct tevent_context *ev,
67 struct tevent_signal *se,
68 int signum, int count, void *siginfo,
72 if (getpgrp() == getpid()) {
74 * We're the process group leader, send
75 * SIGTERM to our process group.
77 DEBUG(0,("SIGTERM: killing children\n"));
78 kill(-getpgrp(), SIGTERM);
81 DEBUG(0,("Exiting pid %u on SIGTERM\n", (unsigned int)getpid()));
87 handle EOF on the parent-to-all-children pipe in the child
89 static void standard_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde,
90 uint16_t flags, void *private_data)
92 DEBUG(10,("Child %d exiting\n", (int)getpid()));
93 talloc_free(event_ctx);
98 handle EOF on the child pipe in the parent, so we know when a
99 process terminates without using SIGCHLD or waiting on all possible pids.
101 We need to ensure we do not ignore SIGCHLD because we need it to
102 work to get a valid error code from samba_runcmd_*().
104 static void standard_child_pipe_handler(struct tevent_context *ev,
105 struct tevent_fd *fde,
109 struct standard_child_state *state
110 = talloc_get_type_abort(private_data, struct standard_child_state);
114 messaging_dgm_cleanup(state->pid);
116 /* the child has closed the pipe, assume its dead */
118 pid = waitpid(state->pid, &status, 0);
120 if (pid != state->pid) {
121 if (errno == ECHILD) {
123 * this happens when the
124 * parent has set SIGCHLD to
125 * SIG_IGN. In that case we
127 * information for the child
128 * via its logging. We should
129 * stop using SIG_IGN on
130 * SIGCHLD in the standard
133 DEBUG(0, ("Error in waitpid() unexpectedly got ECHILD "
134 "for child %d (%s) - %s, someone has set SIGCHLD "
136 (int)state->pid, state->name,
141 DEBUG(0, ("Error in waitpid() for child %d (%s) - %s \n",
142 (int)state->pid, state->name, strerror(errno)));
149 if (WIFEXITED(status)) {
150 status = WEXITSTATUS(status);
152 DBG_ERR("Child %d (%s) exited with status %d\n",
153 (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));
164 static struct standard_child_state *setup_standard_child_pipe(struct tevent_context *ev,
167 struct standard_child_state *state;
168 int parent_child_pipe[2];
172 * Prepare a pipe to allow us to know when the child exits,
173 * because it will trigger a read event on this private
176 * We do all this before the accept and fork(), so we can
177 * clean up if it fails.
179 state = talloc_zero(ev, struct standard_child_state);
188 state->name = talloc_strdup(state, name);
189 if (state->name == NULL) {
194 ret = pipe(parent_child_pipe);
196 DEBUG(0, ("Failed to create parent-child pipe to handle "
197 "SIGCHLD to track new process for socket\n"));
202 smb_set_close_on_exec(parent_child_pipe[0]);
203 smb_set_close_on_exec(parent_child_pipe[1]);
205 state->from_child_fd = parent_child_pipe[0];
206 state->to_parent_fd = parent_child_pipe[1];
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.
214 state->from_child_fde = tevent_add_fd(ev, state,
215 state->from_child_fd,
217 standard_child_pipe_handler,
219 if (state->from_child_fde == NULL) {
223 tevent_fd_set_auto_close(state->from_child_fde);
229 called when a listening socket becomes readable.
231 static void standard_accept_connection(
232 struct tevent_context *ev,
233 struct loadparm_context *lp_ctx,
234 struct socket_context *sock,
235 void (*new_conn)(struct tevent_context *,
236 struct loadparm_context *,
237 struct socket_context *,
242 void *process_context)
245 struct socket_context *sock2;
247 struct socket_address *c, *s;
248 struct standard_child_state *state;
249 struct tevent_fd *fde = NULL;
250 struct tevent_signal *se = NULL;
251 struct process_context *proc_ctx = NULL;
254 /* accept an incoming connection. */
255 status = socket_accept(sock, &sock2);
256 if (!NT_STATUS_IS_OK(status)) {
257 DEBUG(0,("standard_accept_connection: accept: %s\n",
259 /* this looks strange, but is correct. We need to throttle things until
260 the system clears enough resources to handle this new socket */
265 proc_ctx = talloc_get_type_abort(process_context,
266 struct process_context);
268 if (proc_ctx->inhibit_fork_on_accept) {
271 * Service does not support forking a new process on a
272 * new connection, either it's maintaining shared
273 * state or the overhead of forking a new process is a
274 * significant fraction of the response time.
276 talloc_steal(private_data, sock2);
277 new_conn(ev, lp_ctx, sock2,
278 cluster_id(pid, socket_get_fd(sock2)), private_data,
283 state = setup_standard_child_pipe(ev, NULL);
290 close(state->to_parent_fd);
291 state->to_parent_fd = -1;
299 /* parent or error code ... */
301 /* go back to the event loop */
305 /* this leaves state->to_parent_fd open */
308 /* Now in the child code so indicate that we forked
309 * so the terminate code knows what to do
311 proc_ctx->forked_on_accept = true;
314 setproctitle("task[%s] standard worker", proc_ctx->name);
316 /* This is now the child code. We need a completely new event_context to work with */
318 if (tevent_re_initialise(ev) != 0) {
319 smb_panic("Failed to re-initialise tevent after fork");
322 /* this will free all the listening sockets and all state that
323 is not associated with this new connection */
326 /* we don't care if the dup fails, as its only a select()
327 speed optimisation */
330 /* tdb needs special fork handling */
331 ldb_wrap_fork_hook();
333 /* Must be done after a fork() to reset messaging contexts. */
334 status = imessaging_reinit_all();
335 if (!NT_STATUS_IS_OK(status)) {
336 smb_panic("Failed to re-initialise imessaging after fork");
339 fde = tevent_add_fd(ev, ev, proc_ctx->from_parent_fd, TEVENT_FD_READ,
340 standard_pipe_handler, NULL);
342 smb_panic("Failed to add fd handler after fork");
345 se = tevent_add_signal(ev,
349 sighup_signal_handler,
352 smb_panic("Failed to add SIGHUP handler after fork");
355 se = tevent_add_signal(ev,
359 sigterm_signal_handler,
362 smb_panic("Failed to add SIGTERM handler after fork");
365 /* setup the process title */
366 c = socket_get_peer_addr(sock2, ev);
367 s = socket_get_my_addr(sock2, ev);
369 setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
370 c->addr, c->port, s->addr, s->port, (int)pid);
375 /* setup this new connection. Cluster ID is PID based for this process model */
376 new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data,
379 /* we can't return to the top level here, as that event context is gone,
380 so we now process events in the new event context until there are no
382 tevent_loop_wait(ev);
389 called to create a new server task
391 static void standard_new_task(struct tevent_context *ev,
392 struct loadparm_context *lp_ctx,
393 const char *service_name,
394 void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *),
396 const struct service_details *service_details,
401 struct standard_child_state *state;
402 struct tevent_fd *fde = NULL;
403 struct tevent_signal *se = NULL;
404 struct process_context *proc_ctx = NULL;
406 state = setup_standard_child_pipe(ev, service_name);
414 close(state->to_parent_fd);
415 state->to_parent_fd = -1;
423 /* parent or error code ... go back to the event loop */
427 /* this leaves state->to_parent_fd open */
432 /* this will free all the listening sockets and all state that
433 is not associated with this new connection */
434 if (tevent_re_initialise(ev) != 0) {
435 smb_panic("Failed to re-initialise tevent after fork");
438 /* ldb/tdb need special fork handling */
439 ldb_wrap_fork_hook();
441 /* Must be done after a fork() to reset messaging contexts. */
442 status = imessaging_reinit_all();
443 if (!NT_STATUS_IS_OK(status)) {
444 smb_panic("Failed to re-initialise imessaging after fork");
447 fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ,
448 standard_pipe_handler, NULL);
450 smb_panic("Failed to add fd handler after fork");
453 se = tevent_add_signal(ev,
457 sighup_signal_handler,
460 smb_panic("Failed to add SIGHUP handler after fork");
463 se = tevent_add_signal(ev,
467 sigterm_signal_handler,
470 smb_panic("Failed to add SIGTERM handler after fork");
473 setproctitle("task[%s]", service_name);
476 * Set up the process context to be passed through to the terminate
477 * and accept_connection functions
479 proc_ctx = talloc(ev, struct process_context);
480 proc_ctx->name = talloc_strdup(ev, service_name);
481 proc_ctx->from_parent_fd = from_parent_fd;
482 proc_ctx->inhibit_fork_on_accept =
483 service_details->inhibit_fork_on_accept;
484 proc_ctx->forked_on_accept = false;
486 /* setup this new task. Cluster ID is PID based for this process model */
487 new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx);
489 /* we can't return to the top level here, as that event context is gone,
490 so we now process events in the new event context until there are no
492 tevent_loop_wait(ev);
499 /* called when a task goes down */
500 static void standard_terminate(struct tevent_context *ev,
501 struct loadparm_context *lp_ctx,
503 void *process_context)
505 struct process_context *proc_ctx = NULL;
507 DBG_DEBUG("process terminating reason[%s]\n", reason);
508 if (process_context == NULL) {
509 smb_panic("Panicking process_context is NULL");
512 proc_ctx = talloc_get_type(process_context, struct process_context);
513 if (proc_ctx->forked_on_accept == false) {
515 * The current task was not forked on accept, so it needs to
516 * keep running and process requests from other connections
521 * The current process was forked on accept to handle a single
522 * connection/request. That request has now finished and the process
526 /* this reload_charcnv() has the effect of freeing the iconv context memory,
527 which makes leak checking easier */
528 reload_charcnv(lp_ctx);
530 /* Always free event context last before exit. */
533 /* terminate this process */
537 /* called to set a title of a task or connection */
538 static void standard_set_title(struct tevent_context *ev, const char *title)
541 setproctitle("%s", title);
547 static const struct model_ops standard_ops = {
549 .model_init = standard_model_init,
550 .accept_connection = standard_accept_connection,
551 .new_task = standard_new_task,
552 .terminate = standard_terminate,
553 .set_title = standard_set_title,
557 initialise the standard process model, registering ourselves with the process model subsystem
559 NTSTATUS process_model_standard_init(TALLOC_CTX *ctx)
561 return register_process_model(&standard_ops);