From a4887e250b84c321c75d54b9d3adf6fcf7c27fed Mon Sep 17 00:00:00 2001 From: Marc VanHeyningen Date: Tue, 5 May 2009 21:18:50 +0000 Subject: s3: Allow child processes to exit gracefully if we are out of fds 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 --- source3/include/proto.h | 2 +- source3/lib/util.c | 12 ++++++------ source3/nmbd/asyncdns.c | 4 ++-- source3/nmbd/nmbd.c | 4 ++-- source3/printing/print_cups.c | 4 ++-- source3/printing/printing.c | 5 +++-- source3/smbd/server.c | 19 +++++++++++++------ source3/winbindd/winbindd.c | 5 +++-- source3/winbindd/winbindd_dual.c | 5 +++-- 9 files changed, 35 insertions(+), 25 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index c78d2c8e0b..717a972505 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/lib/util.c b/source3/lib/util.c index 13f7e3c9ee..8e67edeae6 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -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; } /**************************************************************************** diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index 0736a66fb8..85729ae7ac 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -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"); } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index daf4c295a6..903dc36d53 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -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); } diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index 7edfb5edbe..18f42138c9 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -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"); } diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 3f337d01be..e73669fef5 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -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"); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 67836f785b..685b26fa1a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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); } diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index e1ce223475..2b25616cf7 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -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); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index a69d34f30c..6fb0b5857c 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -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; } -- cgit