summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Lockyer <gary@catalyst.net.nz>2018-09-07 07:04:48 +1200
committerAndrew Bartlett <abartlet@samba.org>2018-11-30 11:42:44 +0100
commitf90cf49970a0edf4dce5d145726a04e798530a2e (patch)
treeee9ffa2323291ab3cc73dc499959eb1773971b1e
parent2381b4ff6794ba514cca57d3995459bc2cef8352 (diff)
downloadsamba-f90cf49970a0edf4dce5d145726a04e798530a2e.tar.gz
s4 smdb standard: Limit processes forked on accept.
Limit the number of processes started by the standard model on accept. For those services that support fork on accept, the standard model forks a new process for each new connection. This patch limits the number of processes to the value specified in 'max smbd processes', a value of zero indicates that there is no limit on the number of processes that can be forked. Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml7
-rw-r--r--selftest/knownfail.d/process_limit1
-rw-r--r--source4/smbd/process_standard.c33
3 files changed, 38 insertions, 3 deletions
diff --git a/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml b/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml
index a194a26a13c..f5b1e4230be 100644
--- a/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml
+++ b/docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml
@@ -10,6 +10,13 @@
conditions, each user will have an <citerefentry><refentrytitle>smbd</refentrytitle>
<manvolnum>8</manvolnum></citerefentry> associated with him or her to handle connections to all
shares from a given host.</para>
+
+ <para>For a Samba ADDC running the standard process model this option
+ limits the number of processes forked to handle requests.
+ Currently new processes are only forked for ldap and netlogon
+ requests.
+ </para>
+
</description>
<value type="default">0</value>
diff --git a/selftest/knownfail.d/process_limit b/selftest/knownfail.d/process_limit
deleted file mode 100644
index db34dae23ca..00000000000
--- a/selftest/knownfail.d/process_limit
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.process_limits.samba.tests.process_limits.StandardModelProcessLimitTests.test_process_limits
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c
index b1cc7de155d..139339c92ec 100644
--- a/source4/smbd/process_standard.c
+++ b/source4/smbd/process_standard.c
@@ -32,6 +32,9 @@
#include "lib/util/debug.h"
#include "source3/lib/messages_dgm.h"
+static unsigned connections_active = 0;
+static unsigned smbd_max_processes = 0;
+
struct standard_child_state {
const char *name;
pid_t pid;
@@ -143,8 +146,7 @@ static void standard_child_pipe_handler(struct tevent_context *ev,
if (errno == 0) {
errno = ECHILD;
}
- TALLOC_FREE(state);
- return;
+ goto done;
}
if (WIFEXITED(status)) {
status = WEXITSTATUS(status);
@@ -157,7 +159,17 @@ static void standard_child_pipe_handler(struct tevent_context *ev,
DBG_ERR("Child %d (%s) terminated with signal %d\n",
(int)state->pid, state->name, status);
}
+done:
TALLOC_FREE(state);
+ if (smbd_max_processes > 0) {
+ if (connections_active < 1) {
+ DBG_ERR("Number of active connections "
+ "less than 1 (%d)\n",
+ connections_active);
+ connections_active = 1;
+ }
+ connections_active--;
+ }
return;
}
@@ -282,6 +294,21 @@ static void standard_accept_connection(
return;
}
+ if (smbd_max_processes > 0) {
+ if (connections_active >= smbd_max_processes) {
+ DBG_ERR("(%d) connections already active, "
+ "maximum is (%d). Dropping request\n",
+ connections_active,
+ smbd_max_processes);
+ /*
+ * Drop the connection as we're overloaded at the moment
+ */
+ talloc_free(sock2);
+ return;
+ }
+ connections_active++;
+ }
+
state = setup_standard_child_pipe(ev, NULL);
if (state == NULL) {
return;
@@ -486,6 +513,8 @@ static void standard_new_task(struct tevent_context *ev,
service_details->inhibit_fork_on_accept;
proc_ctx->forked_on_accept = false;
+ smbd_max_processes = lpcfg_max_smbd_processes(lp_ctx);
+
/* setup this new task. Cluster ID is PID based for this process model */
task = new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx);
/*