s3: Allow child processes to exit gracefully if we are out of fds
authorMarc VanHeyningen <marc.vanheyningen@isilon.com>
Tue, 5 May 2009 21:18:50 +0000 (21:18 +0000)
committerTim Prouty <tprouty@samba.org>
Wed, 27 May 2009 20:16:17 +0000 (13:16 -0700)
When we run out of file descriptors for some reason, every new
connection forks a child that immediately panics causing smbd to
coredump.  This seems unnecessarily harsh; with this code change we
now catch that error and merely log a message about it and exit
without the core dump.

Signed-off-by: Tim Prouty <tprouty@samba.org>
source3/include/proto.h
source3/lib/util.c
source3/nmbd/asyncdns.c
source3/nmbd/nmbd.c
source3/printing/print_cups.c
source3/printing/printing.c
source3/smbd/server.c
source3/winbindd/winbindd.c
source3/winbindd/winbindd_dual.c

index c78d2c8e0b876c406947015a557a27ede97b902b..717a972505eb9b31be94dbff6e955545ad67dcf4 100644 (file)
@@ -1106,7 +1106,7 @@ char *clean_name(TALLOC_CTX *ctx, const char *s);
 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos);
 int set_blocking(int fd, bool set);
 void smb_msleep(unsigned int t);
-bool reinit_after_fork(struct messaging_context *msg_ctx,
+NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
                       struct event_context *ev_ctx,
                       bool parent_longlived);
 bool yesno(const char *p);
index 13f7e3c9ee9199097a3c96245993e3058c239914..8e67edeae6b9056d7d5e9ad6d43d58a54770da54 100644 (file)
@@ -927,11 +927,11 @@ void smb_msleep(unsigned int t)
 #endif
 }
 
-bool reinit_after_fork(struct messaging_context *msg_ctx,
+NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
                       struct event_context *ev_ctx,
                       bool parent_longlived)
 {
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
        /* Reset the state of the random
         * number generation system, so
@@ -942,7 +942,8 @@ bool reinit_after_fork(struct messaging_context *msg_ctx,
        /* tdb needs special fork handling */
        if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
                DEBUG(0,("tdb_reopen_all failed.\n"));
-               return false;
+               status = NT_STATUS_OPEN_FAILED;
+               goto done;
        }
 
        if (ev_ctx) {
@@ -958,11 +959,10 @@ bool reinit_after_fork(struct messaging_context *msg_ctx,
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,("messaging_reinit() failed: %s\n",
                                 nt_errstr(status)));
-                       return false;
                }
        }
-
-       return true;
+ done:
+       return status;
 }
 
 /****************************************************************************
index 0736a66fb8a9bc570aa050230ee3b01d90e2b4a0..85729ae7ac9957584131b4c57ea715f6c8b560c1 100644 (file)
@@ -164,8 +164,8 @@ void start_async_dns(void)
        CatchSignal(SIGHUP, SIG_IGN);
         CatchSignal(SIGTERM, SIGNAL_CAST sig_term );
 
-       if (!reinit_after_fork(nmbd_messaging_context(),
-                              nmbd_event_context(), true)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(),
+                                              nmbd_event_context(), true))) {
                DEBUG(0,("reinit_after_fork() failed\n"));
                smb_panic("reinit_after_fork() failed");
        }
index daf4c295a667e5e26726333c0414119747fabb3b..903dc36d533d5c61cf0a0e2faeede076abf94ac8 100644 (file)
@@ -913,8 +913,8 @@ static bool open_sockets(bool isdaemon, int port)
 
        pidfile_create("nmbd");
 
-       if (!reinit_after_fork(nmbd_messaging_context(),
-                              nmbd_event_context(), false)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(),
+                                              nmbd_event_context(), false))) {
                DEBUG(0,("reinit_after_fork() failed\n"));
                exit(1);
        }
index 7edfb5edbeb61cc49288286ce3b6c0075823e162..18f42138c910df95878af8a52d2a7626a351f906 100644 (file)
@@ -433,8 +433,8 @@ static bool cups_pcap_load_async(int *pfd)
 
        close_all_print_db();
 
-       if (!reinit_after_fork(smbd_messaging_context(),
-                              smbd_event_context(), true)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(),
+                                              smbd_event_context(), true))) {
                DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
                smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
        }
index 3f337d01bee3fd850cd5ddd785dd9c90c3811904..e73669fef5b149246fd218e5cf7c5649cf17d4a4 100644 (file)
@@ -1436,8 +1436,9 @@ void start_background_queue(void)
                close(pause_pipe[0]);
                pause_pipe[0] = -1;
 
-               if (!reinit_after_fork(smbd_messaging_context(),
-                                      smbd_event_context(), true)) {
+               if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(),
+                                                      smbd_event_context(),
+                                                      true))) {
                        DEBUG(0,("reinit_after_fork() failed\n"));
                        smb_panic("reinit_after_fork() failed");
                }
index 67836f785b489c8e022d10e1aa8ded2f78a8dd15..685b26fa1ae981427b699149d5b8bb72da65097a 100644 (file)
@@ -356,6 +356,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
 
        pid = sys_fork();
        if (pid == 0) {
+               NTSTATUS status = NT_STATUS_OK;
                /* Child code ... */
                am_parent = 0;
 
@@ -374,10 +375,15 @@ static void smbd_accept_connection(struct tevent_context *ev,
                talloc_free(s->parent);
                s = NULL;
 
-               if (!reinit_after_fork(
-                           smbd_messaging_context(),
-                           smbd_event_context(),
-                           true)) {
+               status = reinit_after_fork(smbd_messaging_context(),
+                                          smbd_event_context(), true);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status,
+                                           NT_STATUS_TOO_MANY_OPENED_FILES)) {
+                               DEBUG(0,("child process cannot initialize "
+                                        "because too many files are open\n"));
+                               goto exit;
+                       }
                        DEBUG(0,("reinit_after_fork() failed\n"));
                        smb_panic("reinit_after_fork() failed");
                }
@@ -386,6 +392,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
                smbd_setup_sig_hup_handler();
 
                smbd_process();
+        exit:
                exit_server_cleanly("end of child");
                return;
        } else if (pid < 0) {
@@ -1122,8 +1129,8 @@ extern void build_options(bool screen);
        if (is_daemon)
                pidfile_create("smbd");
 
-       if (!reinit_after_fork(smbd_messaging_context(),
-                              smbd_event_context(), false)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(),
+                            smbd_event_context(), false))) {
                DEBUG(0,("reinit_after_fork() failed\n"));
                exit(1);
        }
index e1ce2234759dd9b26be7432a586e6e3abbf07cb2..2b25616cf765755cfb77ac7752965f8cd00d3842 100644 (file)
@@ -1304,8 +1304,9 @@ int main(int argc, char **argv, char **envp)
         * winbindd-specific resources we must free yet. JRA.
         */
 
-       if (!reinit_after_fork(winbind_messaging_context(),
-                              winbind_event_context(), false)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(),
+                                              winbind_event_context(),
+                                              false))) {
                DEBUG(0,("reinit_after_fork() failed\n"));
                exit(1);
        }
index a69d34f30c9fb5ac07b0219f0c5d502995dc684f..6fb0b5857c894b6d63d8a4f7a4a6a9e57646c74c 100644 (file)
@@ -1121,8 +1121,9 @@ bool winbindd_reinit_after_fork(const char *logfilename)
        struct winbindd_domain *domain;
        struct winbindd_child *cl;
 
-       if (!reinit_after_fork(winbind_messaging_context(),
-                              winbind_event_context(), true)) {
+       if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(),
+                                              winbind_event_context(),
+                                              true))) {
                DEBUG(0,("reinit_after_fork() failed\n"));
                return false;
        }