summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorTim Beale <timbeale@catalyst.net.nz>2018-11-22 10:35:01 +1300
committerAndrew Bartlett <abartlet@samba.org>2018-11-23 11:40:49 +0100
commitfabc3c9d3827fd30d7cec674105218c97c04e801 (patch)
treec9ff78debfa59d38ca6a7648b05ffa6bff673968 /source4
parent830a65020475886af6bd1edc347c0a2b96d14a38 (diff)
downloadsamba-fabc3c9d3827fd30d7cec674105218c97c04e801.tar.gz
source4 smbd prefork: Add code comments
Add some comments to the prefork code explaining what's going on. Signed-off-by: Tim Beale <timbeale@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Fri Nov 23 11:40:49 CET 2018 on sn-devel-144
Diffstat (limited to 'source4')
-rw-r--r--source4/smbd/process_prefork.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/source4/smbd/process_prefork.c b/source4/smbd/process_prefork.c
index c62f08fbbfe..49446d23b5a 100644
--- a/source4/smbd/process_prefork.c
+++ b/source4/smbd/process_prefork.c
@@ -22,7 +22,16 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
+/*
+ * The pre-fork process model distributes the server workload amongst several
+ * designated worker threads (e.g. 'prefork-worker-ldap-0',
+ * 'prefork-worker-ldap-1', etc). The number of worker threads is controlled
+ * by the 'prefork children' conf setting. The worker threads are controlled
+ * by a prefork master process (e.g. 'prefork-master-ldap'). The prefork master
+ * doesn't handle the server workload (i.e. processing messages) itself, but is
+ * responsible for restarting workers if they exit unexpectedly. The top-level
+ * samba process is responsible for restarting the master process if it exits.
+ */
#include "includes.h"
#include <unistd.h>
@@ -181,8 +190,10 @@ static void irpc_cleanup(
}
/*
- handle EOF on the parent-to-all-children pipe in the child
-*/
+ * handle EOF on the parent-to-all-children pipe in the child, i.e.
+ * the parent has died and its end of the pipe has been closed.
+ * The child handles this by exiting as well.
+ */
static void prefork_pipe_handler(struct tevent_context *event_ctx,
struct tevent_fd *fde, uint16_t flags,
void *private_data)
@@ -209,7 +220,7 @@ static void prefork_pipe_handler(struct tevent_context *event_ctx,
/*
- * called to create a new server task
+ * Called by the top-level samba process to create a new prefork master process
*/
static void prefork_fork_master(
struct tevent_context *ev,
@@ -354,6 +365,13 @@ static void prefork_fork_master(
}
DBG_NOTICE("Forking %d %s worker processes\n",
num_children, service_name);
+
+ /*
+ * the prefork master creates its own control pipe, so the prefork
+ * workers can detect if the master exits (in which case an EOF gets
+ * written). (Whereas from_parent_fd is the control pipe from the
+ * top-level process that the prefork master listens on)
+ */
{
int ret;
ret = pipe(control_pipe);
@@ -386,8 +404,11 @@ static void prefork_fork_master(
/* We need to keep ev2 until we're finished for the messaging to work */
TALLOC_FREE(ev2);
exit(0);
-
}
+
+/*
+ * Restarts a child process if it exits unexpectedly
+ */
static void prefork_restart(struct tevent_context *ev,
struct restart_context *rc)
{
@@ -396,6 +417,11 @@ static void prefork_restart(struct tevent_context *ev,
unsigned restart_delay = rc->restart_delay;
unsigned default_value = 0;
+ /*
+ * If the child process is constantly exiting, then restarting it can
+ * consume a lot of resources. In which case, we want to backoff a bit
+ * before respawning it
+ */
default_value = lpcfg_prefork_backoff_increment(rc->lp_ctx);
backoff = lpcfg_parm_int(rc->lp_ctx,
NULL,
@@ -447,6 +473,7 @@ static void prefork_restart(struct tevent_context *ev,
&pd);
}
}
+
/*
handle EOF on the child pipe in the parent, so we know when a
process terminates without using SIGCHLD or waiting on all possible pids.
@@ -585,6 +612,9 @@ static void setup_handlers(
}
}
+/*
+ * Called by the prefork master to create a new prefork worker process
+ */
static void prefork_fork_worker(struct task_server *task,
struct tevent_context *ev,
struct tevent_context *ev2,
@@ -609,6 +639,10 @@ static void prefork_fork_worker(struct task_server *task,
int fd = tfork_event_fd(w);
struct restart_context *rc = NULL;
+ /*
+ * we're the parent (prefork master), so store enough info to
+ * restart the worker/child if it exits unexpectedly
+ */
rc = talloc_zero(ev, struct restart_context);
if (rc == NULL) {
smb_panic("OOM allocating restart context\n");
@@ -637,8 +671,15 @@ static void prefork_fork_worker(struct task_server *task,
}
tevent_fd_set_auto_close(fde);
} else {
+
+ /*
+ * we're the child (prefork-worker). We never write to the
+ * control pipe, but listen on the read end in case our parent
+ * (the pre-fork master) exits
+ */
close(control_pipe[1]);
setup_handlers(ev2, lp_ctx, control_pipe[0]);
+
/*
* tfork uses malloc
*/