2 Unix SMB/CIFS implementation.
4 process model: prefork (n client connections per process)
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 Copyright (C) Andrew Bartlett 2008 <abartlet@samba.org>
10 Copyright (C) David Disseldorp 2008 <ddiss@sgi.com>
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 * The pre-fork process model distributes the server workload amongst several
27 * designated worker threads (e.g. 'prefork-worker-ldap-0',
28 * 'prefork-worker-ldap-1', etc). The number of worker threads is controlled
29 * by the 'prefork children' conf setting. The worker threads are controlled
30 * by a prefork master process (e.g. 'prefork-master-ldap'). The prefork master
31 * doesn't handle the server workload (i.e. processing messages) itself, but is
32 * responsible for restarting workers if they exit unexpectedly. The top-level
33 * samba process is responsible for restarting the master process if it exits.
38 #include "lib/events/events.h"
39 #include "lib/messaging/messaging.h"
40 #include "lib/socket/socket.h"
41 #include "samba/process_model.h"
42 #include "cluster/cluster.h"
43 #include "param/param.h"
45 #include "lib/util/tfork.h"
46 #include "lib/messaging/irpc.h"
47 #include "lib/util/util_process.h"
48 #include "server_util.h"
50 #define min(a, b) (((a) < (b)) ? (a) : (b))
52 NTSTATUS
process_model_prefork_init(void);
53 static void prefork_new_task(
54 struct tevent_context
*ev
,
55 struct loadparm_context
*lp_ctx
,
56 const char *service_name
,
57 struct task_server
*(*new_task_fn
)(struct tevent_context
*,
58 struct loadparm_context
*lp_ctx
,
63 const struct service_details
*service_details
,
65 static void prefork_fork_worker(struct task_server
*task
,
66 struct tevent_context
*ev
,
67 struct tevent_context
*ev2
,
68 struct loadparm_context
*lp_ctx
,
69 const struct service_details
*service_details
,
70 const char *service_name
,
72 unsigned restart_delay
,
73 struct process_details
*pd
);
74 static void prefork_child_pipe_handler(struct tevent_context
*ev
,
75 struct tevent_fd
*fde
,
78 static void setup_handlers(struct tevent_context
*ev
,
79 struct loadparm_context
*lp_ctx
,
83 * State needed to restart the master process or a worker process if they
86 struct master_restart_context
{
87 struct task_server
*(*new_task_fn
)(struct tevent_context
*,
88 struct loadparm_context
*lp_ctx
,
95 struct worker_restart_context
{
96 unsigned int instance
;
97 struct task_server
*task
;
98 struct tevent_context
*ev2
;
102 struct restart_context
{
103 struct loadparm_context
*lp_ctx
;
106 const struct service_details
*service_details
;
107 const char *service_name
;
108 unsigned restart_delay
;
109 struct master_restart_context
*master
;
110 struct worker_restart_context
*worker
;
113 static void sighup_signal_handler(struct tevent_context
*ev
,
114 struct tevent_signal
*se
,
115 int signum
, int count
, void *siginfo
,
118 reopen_logs_internal();
121 static void sigterm_signal_handler(struct tevent_context
*ev
,
122 struct tevent_signal
*se
,
123 int signum
, int count
, void *siginfo
,
127 if (getpgrp() == getpid()) {
129 * We're the process group leader, send
130 * SIGTERM to our process group.
132 DBG_NOTICE("SIGTERM: killing children\n");
133 kill(-getpgrp(), SIGTERM
);
136 DBG_NOTICE("Exiting pid %d on SIGTERM\n", getpid());
142 called when the process model is selected
144 static void prefork_model_init(void)
148 static void prefork_reload_after_fork(void)
152 ldb_wrap_fork_hook();
153 /* Must be done after a fork() to reset messaging contexts. */
154 status
= imessaging_reinit_all();
155 if (!NT_STATUS_IS_OK(status
)) {
156 smb_panic("Failed to re-initialise imessaging after fork");
158 force_check_log_size();
162 * clean up any messaging associated with the old process.
165 static void irpc_cleanup(
166 struct loadparm_context
*lp_ctx
,
167 struct tevent_context
*ev
,
170 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
171 struct imessaging_context
*msg_ctx
= NULL
;
172 NTSTATUS status
= NT_STATUS_OK
;
174 if (mem_ctx
== NULL
) {
175 DBG_ERR("OOM cleaning up irpc\n");
178 msg_ctx
= imessaging_client_init(mem_ctx
, lp_ctx
, ev
);
179 if (msg_ctx
== NULL
) {
180 DBG_ERR("Unable to create imessaging_context\n");
181 TALLOC_FREE(mem_ctx
);
184 status
= imessaging_process_cleanup(msg_ctx
, pid
);
185 if (!NT_STATUS_IS_OK(status
)) {
186 DBG_ERR("imessaging_process_cleanup returned (%s)\n",
188 TALLOC_FREE(mem_ctx
);
192 TALLOC_FREE(mem_ctx
);
196 * handle EOF on the parent-to-all-children pipe in the child, i.e.
197 * the parent has died and its end of the pipe has been closed.
198 * The child handles this by exiting as well.
200 static void prefork_pipe_handler(struct tevent_context
*event_ctx
,
201 struct tevent_fd
*fde
, uint16_t flags
,
204 struct loadparm_context
*lp_ctx
= NULL
;
208 * free the fde which removes the event and stops it firing again
213 * Clean up any irpc end points this process had.
216 lp_ctx
= talloc_get_type_abort(private_data
, struct loadparm_context
);
217 irpc_cleanup(lp_ctx
, event_ctx
, pid
);
219 DBG_NOTICE("Child %d exiting\n", getpid());
220 TALLOC_FREE(event_ctx
);
226 * Called by the top-level samba process to create a new prefork master process
228 static void prefork_fork_master(
229 struct tevent_context
*ev
,
230 struct loadparm_context
*lp_ctx
,
231 const char *service_name
,
232 struct task_server
*(*new_task_fn
)(struct tevent_context
*,
233 struct loadparm_context
*lp_ctx
,
238 const struct service_details
*service_details
,
239 unsigned restart_delay
,
243 struct tfork
* t
= NULL
;
246 struct tevent_context
*ev2
;
247 struct task_server
*task
= NULL
;
248 struct process_details pd
= initial_process_details
;
249 struct samba_tevent_trace_state
*samba_tevent_trace_state
= NULL
;
254 smb_panic("failure in tfork\n");
257 DBG_NOTICE("Forking [%s] pre-fork master process\n", service_name
);
258 pid
= tfork_child_pid(t
);
260 struct tevent_fd
*fde
= NULL
;
261 int fd
= tfork_event_fd(t
);
262 struct restart_context
*rc
= NULL
;
264 /* Register a pipe handler that gets called when the prefork
265 * master process terminates.
267 rc
= talloc_zero(ev
, struct restart_context
);
269 smb_panic("OOM allocating restart context\n");
273 rc
->service_name
= service_name
;
274 rc
->service_details
= service_details
;
275 rc
->from_parent_fd
= from_parent_fd
;
276 rc
->restart_delay
= restart_delay
;
277 rc
->master
= talloc_zero(rc
, struct master_restart_context
);
278 if (rc
->master
== NULL
) {
279 smb_panic("OOM allocating master restart context\n");
282 rc
->master
->new_task_fn
= new_task_fn
;
283 rc
->master
->private_data
= private_data
;
286 ev
, ev
, fd
, TEVENT_FD_READ
, prefork_child_pipe_handler
, rc
);
288 smb_panic("Failed to add child pipe handler, "
291 tevent_fd_set_auto_close(fde
);
296 setproctitle("task[%s] pre-fork master", service_name
);
298 * We must fit within 15 chars of text or we will truncate, so
299 * we put the constant part last
301 prctl_set_comment("%s[master]", service_name
);
304 * this will free all the listening sockets and all state that
305 * is not associated with this new connection
307 if (tevent_re_initialise(ev
) != 0) {
308 smb_panic("Failed to re-initialise tevent after fork");
310 prefork_reload_after_fork();
311 setup_handlers(ev
, lp_ctx
, from_parent_fd
);
313 if (service_details
->inhibit_pre_fork
) {
315 ev
, lp_ctx
, cluster_id(pid
, 0), private_data
, NULL
);
317 * The task does not support pre-fork
319 if (task
!= NULL
&& service_details
->post_fork
!= NULL
) {
320 service_details
->post_fork(task
, &pd
);
322 tevent_loop_wait(ev
);
328 * This is now the child code. We need a completely new event_context
331 ev2
= s4_event_context_init(NULL
);
333 samba_tevent_trace_state
= create_samba_tevent_trace_state(ev2
);
334 if (samba_tevent_trace_state
== NULL
) {
340 tevent_set_trace_callback(ev2
,
341 samba_tevent_trace_callback
,
342 samba_tevent_trace_state
);
344 /* setup this new connection: process will bind to it's sockets etc
346 * While we can use ev for the child, which has been re-initialised
347 * above we must run the new task under ev2 otherwise the children would
348 * be listening on the sockets. Also we don't want the top level
349 * process accepting and handling requests, it's responsible for
350 * monitoring and controlling the child work processes.
352 task
= new_task_fn(ev2
, lp_ctx
, cluster_id(pid
, 0), private_data
, NULL
);
360 * Register an irpc name that can be used by the samba-tool processes
364 struct talloc_ctx
*ctx
= talloc_new(NULL
);
367 DBG_ERR("Out of memory");
370 name
= talloc_asprintf(ctx
, "prefork-master-%s", service_name
);
371 irpc_add_name(task
->msg_ctx
, name
);
376 int default_children
;
377 default_children
= lpcfg_prefork_children(lp_ctx
);
378 num_children
= lpcfg_parm_int(lp_ctx
, NULL
, "prefork children",
379 service_name
, default_children
);
381 if (num_children
== 0) {
382 DBG_WARNING("Number of pre-fork children for %s is zero, "
383 "NO worker processes will be started for %s\n",
384 service_name
, service_name
);
386 DBG_NOTICE("Forking %d %s worker processes\n",
387 num_children
, service_name
);
390 * the prefork master creates its own control pipe, so the prefork
391 * workers can detect if the master exits (in which case an EOF gets
392 * written). (Whereas from_parent_fd is the control pipe from the
393 * top-level process that the prefork master listens on)
397 ret
= pipe(control_pipe
);
399 smb_panic("Unable to create worker control pipe\n");
401 smb_set_close_on_exec(control_pipe
[0]);
402 smb_set_close_on_exec(control_pipe
[1]);
406 * We are now free to spawn some worker processes
408 for (i
=0; i
< num_children
; i
++) {
409 prefork_fork_worker(task
,
421 /* Don't listen on the sockets we just gave to the children */
422 tevent_loop_wait(ev
);
424 /* We need to keep ev2 until we're finished for the messaging to work */
430 * Restarts a child process if it exits unexpectedly
432 static void prefork_restart(struct tevent_context
*ev
,
433 struct restart_context
*rc
)
435 unsigned max_backoff
= 0;
436 unsigned backoff
= 0;
437 unsigned restart_delay
= rc
->restart_delay
;
438 unsigned default_value
= 0;
441 * If the child process is constantly exiting, then restarting it can
442 * consume a lot of resources. In which case, we want to backoff a bit
443 * before respawning it
445 default_value
= lpcfg_prefork_backoff_increment(rc
->lp_ctx
);
446 backoff
= lpcfg_parm_int(rc
->lp_ctx
,
448 "prefork backoff increment",
452 default_value
= lpcfg_prefork_maximum_backoff(rc
->lp_ctx
);
453 max_backoff
= lpcfg_parm_int(rc
->lp_ctx
,
455 "prefork maximum backoff",
459 if (restart_delay
> 0) {
460 DBG_ERR("Restarting [%s] pre-fork %s in (%d) seconds\n",
462 (rc
->master
== NULL
) ? "worker" : "master",
464 sleep(restart_delay
);
466 restart_delay
+= backoff
;
467 restart_delay
= min(restart_delay
, max_backoff
);
469 if (rc
->master
!= NULL
) {
470 DBG_ERR("Restarting [%s] pre-fork master\n", rc
->service_name
);
471 prefork_fork_master(ev
,
474 rc
->master
->new_task_fn
,
475 rc
->master
->private_data
,
479 } else if (rc
->worker
!= NULL
) {
480 struct process_details pd
= initial_process_details
;
481 DBG_ERR("Restarting [%s] pre-fork worker(%d)\n",
483 rc
->worker
->instance
);
484 pd
.instances
= rc
->worker
->instance
;
485 prefork_fork_worker(rc
->worker
->task
,
491 rc
->worker
->control_pipe
,
498 handle EOF on the child pipe in the parent, so we know when a
499 process terminates without using SIGCHLD or waiting on all possible pids.
501 We need to ensure we do not ignore SIGCHLD because we need it to
502 work to get a valid error code from samba_runcmd_*().
504 static void prefork_child_pipe_handler(struct tevent_context
*ev
,
505 struct tevent_fd
*fde
,
509 struct restart_context
*rc
= NULL
;
513 /* free the fde which removes the event and stops it firing again */
516 /* the child has closed the pipe, assume its dead */
518 rc
= talloc_get_type_abort(private_data
, struct restart_context
);
519 pid
= tfork_child_pid(rc
->t
);
522 irpc_cleanup(rc
->lp_ctx
, ev
, pid
);
523 status
= tfork_status(&rc
->t
, false);
525 DBG_ERR("Parent %d, Child %d terminated, "
526 "unable to get status code from tfork\n",
528 prefork_restart(ev
, rc
);
529 } else if (WIFEXITED(status
)) {
530 status
= WEXITSTATUS(status
);
531 DBG_ERR("Parent %d, Child %d exited with status %d\n",
532 getpid(), pid
, status
);
534 prefork_restart(ev
, rc
);
536 } else if (WIFSIGNALED(status
)) {
537 status
= WTERMSIG(status
);
538 DBG_ERR("Parent %d, Child %d terminated with signal %d\n",
539 getpid(), pid
, status
);
540 if (status
== SIGABRT
|| status
== SIGBUS
|| status
== SIGFPE
||
541 status
== SIGILL
|| status
== SIGSYS
|| status
== SIGSEGV
||
544 prefork_restart(ev
, rc
);
547 /* tfork allocates tfork structures with malloc */
548 tfork_destroy(&rc
->t
);
555 called when a listening socket becomes readable.
557 static void prefork_accept_connection(
558 struct tevent_context
*ev
,
559 struct loadparm_context
*lp_ctx
,
560 struct socket_context
*listen_socket
,
561 void (*new_conn
)(struct tevent_context
*,
562 struct loadparm_context
*,
563 struct socket_context
*,
568 void *process_context
)
571 struct socket_context
*connected_socket
;
572 pid_t pid
= getpid();
574 /* accept an incoming connection. */
575 status
= socket_accept(listen_socket
, &connected_socket
);
576 if (!NT_STATUS_IS_OK(status
)) {
578 * For prefork we can ignore STATUS_MORE_ENTRIES, as once a
579 * connection becomes available all waiting processes are
580 * woken, but only one gets work to process.
581 * AKA the thundering herd.
582 * In the short term this should not be an issue as the number
583 * of workers should be a small multiple of the number of cpus
584 * In the longer term socket_accept needs to implement a
585 * mutex/semaphore (like apache does) to serialise the accepts
587 if (!NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
588 DBG_ERR("Worker process (%d), error in accept [%s]\n",
589 getpid(), nt_errstr(status
));
594 talloc_steal(private_data
, connected_socket
);
596 new_conn(ev
, lp_ctx
, connected_socket
,
597 cluster_id(pid
, socket_get_fd(connected_socket
)),
598 private_data
, process_context
);
601 static void setup_handlers(
602 struct tevent_context
*ev
,
603 struct loadparm_context
*lp_ctx
,
606 struct tevent_fd
*fde
= NULL
;
607 struct tevent_signal
*se
= NULL
;
609 fde
= tevent_add_fd(ev
, ev
, from_parent_fd
, TEVENT_FD_READ
,
610 prefork_pipe_handler
, lp_ctx
);
612 smb_panic("Failed to add fd handler after fork");
615 se
= tevent_add_signal(ev
,
619 sighup_signal_handler
,
622 smb_panic("Failed to add SIGHUP handler after fork");
625 se
= tevent_add_signal(ev
,
629 sigterm_signal_handler
,
632 smb_panic("Failed to add SIGTERM handler after fork");
637 * Called by the prefork master to create a new prefork worker process
639 static void prefork_fork_worker(struct task_server
*task
,
640 struct tevent_context
*ev
,
641 struct tevent_context
*ev2
,
642 struct loadparm_context
*lp_ctx
,
643 const struct service_details
*service_details
,
644 const char *service_name
,
646 unsigned restart_delay
,
647 struct process_details
*pd
)
649 struct tfork
*w
= NULL
;
654 smb_panic("failure in tfork\n");
657 pid
= tfork_child_pid(w
);
659 struct tevent_fd
*fde
= NULL
;
660 int fd
= tfork_event_fd(w
);
661 struct restart_context
*rc
= NULL
;
664 * we're the parent (prefork master), so store enough info to
665 * restart the worker/child if it exits unexpectedly
667 rc
= talloc_zero(ev
, struct restart_context
);
669 smb_panic("OOM allocating restart context\n");
673 rc
->service_name
= service_name
;
674 rc
->service_details
= service_details
;
675 rc
->restart_delay
= restart_delay
;
677 rc
->worker
= talloc_zero(rc
, struct worker_restart_context
);
678 if (rc
->worker
== NULL
) {
679 smb_panic("OOM allocating master restart context\n");
681 rc
->worker
->ev2
= ev2
;
682 rc
->worker
->instance
= pd
->instances
;
683 rc
->worker
->task
= task
;
684 rc
->worker
->control_pipe
[0] = control_pipe
[0];
685 rc
->worker
->control_pipe
[1] = control_pipe
[1];
688 ev
, ev
, fd
, TEVENT_FD_READ
, prefork_child_pipe_handler
, rc
);
690 smb_panic("Failed to add child pipe handler, "
693 tevent_fd_set_auto_close(fde
);
697 * we're the child (prefork-worker). We never write to the
698 * control pipe, but listen on the read end in case our parent
699 * (the pre-fork master) exits
701 close(control_pipe
[1]);
702 setup_handlers(ev2
, lp_ctx
, control_pipe
[0]);
710 setproctitle("task[%s] pre-forked worker(%d)",
714 * We must fit within 15 chars of text or we will truncate, so
715 * we put child number last
717 prctl_set_comment("%s(%d)",
720 prefork_reload_after_fork();
721 if (service_details
->post_fork
!= NULL
) {
722 service_details
->post_fork(task
, pd
);
725 struct talloc_ctx
*ctx
= talloc_new(NULL
);
728 smb_panic("OOM allocating talloc context\n");
730 name
= talloc_asprintf(ctx
,
731 "prefork-worker-%s-%d",
734 irpc_add_name(task
->msg_ctx
, name
);
737 tevent_loop_wait(ev2
);
743 * called to create a new server task
745 static void prefork_new_task(
746 struct tevent_context
*ev
,
747 struct loadparm_context
*lp_ctx
,
748 const char *service_name
,
749 struct task_server
*(*new_task_fn
)(struct tevent_context
*,
750 struct loadparm_context
*lp_ctx
,
751 struct server_id
, void *, void *),
753 const struct service_details
*service_details
,
756 prefork_fork_master(ev
,
768 * called when a task terminates
770 static void prefork_terminate_task(struct tevent_context
*ev
,
771 struct loadparm_context
*lp_ctx
,
774 void *process_context
)
776 DBG_DEBUG("called with reason[%s]\n", reason
);
786 * called when a connection completes
788 static void prefork_terminate_connection(struct tevent_context
*ev
,
789 struct loadparm_context
*lp_ctx
,
791 void *process_context
)
795 /* called to set a title of a task or connection */
796 static void prefork_set_title(struct tevent_context
*ev
, const char *title
)
800 static const struct model_ops prefork_ops
= {
802 .model_init
= prefork_model_init
,
803 .accept_connection
= prefork_accept_connection
,
804 .new_task
= prefork_new_task
,
805 .terminate_task
= prefork_terminate_task
,
806 .terminate_connection
= prefork_terminate_connection
,
807 .set_title
= prefork_set_title
,
811 * initialise the prefork process model, registering ourselves with the
812 * process model subsystem
814 NTSTATUS
process_model_prefork_init(void)
816 return register_process_model(&prefork_ops
);