s4 smdb standard: Limit processes forked on accept.
authorGary Lockyer <gary@catalyst.net.nz>
Thu, 6 Sep 2018 19:04:48 +0000 (07:04 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 30 Nov 2018 10:42:44 +0000 (11:42 +0100)
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>
docs-xml/smbdotconf/tuning/maxsmbdprocesses.xml
selftest/knownfail.d/process_limit [deleted file]
source4/smbd/process_standard.c

index a194a26a13c3cd493d32c5246c446f5fbaae2263..f5b1e4230be6fa3afd8ac95b2a545593fc53a1eb 100644 (file)
     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 (file)
index db34dae..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.process_limits.samba.tests.process_limits.StandardModelProcessLimitTests.test_process_limits
index b1cc7de155d0b3c0ed901d5bd3d84b4add0aab09..139339c92ec2108c58db293b233c7a57900e4d95 100644 (file)
@@ -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);
        /*