X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Fserver.c;h=f351b995018de95154dd79172d565662e5054acb;hb=c51da257699e7900aa2069eb71eb530e66f35fcc;hp=1786be65900ef14bcad36674d54ae472846a36f4;hpb=63c7107c4affa3992e9c05647b81ecbfe87be01e;p=kai%2Fsamba.git diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1786be65900..f351b995018 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -42,6 +42,37 @@ #include "lib/id_cache.h" #include "lib/param/param.h" +struct smbd_open_socket; +struct smbd_child_pid; + +struct smbd_parent_context { + bool interactive; + + struct tevent_context *ev_ctx; + struct messaging_context *msg_ctx; + + /* the list of listening sockets */ + struct smbd_open_socket *sockets; + + /* the list of current child processes */ + struct smbd_child_pid *children; + size_t num_children; + + struct timed_event *cleanup_te; +}; + +struct smbd_open_socket { + struct smbd_open_socket *prev, *next; + struct smbd_parent_context *parent; + int fd; + struct tevent_fd *fde; +}; + +struct smbd_child_pid { + struct smbd_child_pid *prev, *next; + pid_t pid; +}; + extern void start_epmd(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx); @@ -117,20 +148,6 @@ static void killkids(void) if(am_parent) kill(0,SIGTERM); } -/**************************************************************************** - Process a sam sync message - not sure whether to do this here or - somewhere else. -****************************************************************************/ - -static void msg_sam_sync(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) -{ - DEBUG(10, ("** sam sync message received, ignoring\n")); -} - static void msg_exit_server(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -178,10 +195,16 @@ NTSTATUS messaging_send_to_children(struct messaging_context *msg_ctx, uint32_t msg_type, DATA_BLOB* data) { NTSTATUS status; - struct child_pid *child; + struct smbd_parent_context *parent = am_parent; + struct smbd_child_pid *child; + + if (parent == NULL) { + return NT_STATUS_INTERNAL_ERROR; + } - for (child = children; child != NULL; child = child->next) { - status = messaging_send(msg_ctx, pid_to_procid(child->pid), + for (child = parent->children; child != NULL; child = child->next) { + status = messaging_send(parent->msg_ctx, + pid_to_procid(child->pid), msg_type, data); if (!NT_STATUS_IS_OK(status)) { return status; @@ -207,18 +230,19 @@ static void smbd_msg_debug(struct messaging_context *msg_ctx, messaging_send_to_children(msg_ctx, MSG_DEBUG, data); } -static void add_child_pid(pid_t pid) +static void add_child_pid(struct smbd_parent_context *parent, + pid_t pid) { - struct child_pid *child; + struct smbd_child_pid *child; - child = SMB_MALLOC_P(struct child_pid); + child = talloc_zero(parent, struct smbd_child_pid); if (child == NULL) { DEBUG(0, ("Could not add child struct -- malloc failed\n")); return; } child->pid = pid; - DLIST_ADD(children, child); - num_children += 1; + DLIST_ADD(parent->children, child); + parent->num_children += 1; } /* @@ -237,22 +261,24 @@ static void cleanup_timeout_fn(struct event_context *event_ctx, struct timeval now, void *private_data) { - struct timed_event **cleanup_te = (struct timed_event **)private_data; + struct smbd_parent_context *parent = + talloc_get_type_abort(private_data, + struct smbd_parent_context); + + parent->cleanup_te = NULL; DEBUG(1,("Cleaning up brl and lock database after unclean shutdown\n")); - message_send_all(smbd_messaging_context(), MSG_SMB_UNLOCK, NULL, 0, NULL); - messaging_send_buf(smbd_messaging_context(), procid_self(), - MSG_SMB_BRL_VALIDATE, NULL, 0); - /* mark the cleanup as having been done */ - (*cleanup_te) = NULL; + message_send_all(parent->msg_ctx, MSG_SMB_UNLOCK, NULL, 0, NULL); + messaging_send_buf(parent->msg_ctx, + messaging_server_id(parent->msg_ctx), + MSG_SMB_BRL_VALIDATE, NULL, 0); } -static void remove_child_pid(struct tevent_context *ev_ctx, +static void remove_child_pid(struct smbd_parent_context *parent, pid_t pid, bool unclean_shutdown) { - struct child_pid *child; - static struct timed_event *cleanup_te; + struct smbd_child_pid *child; struct server_id child_id; if (unclean_shutdown) { @@ -262,31 +288,31 @@ static void remove_child_pid(struct tevent_context *ev_ctx, */ DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", (unsigned int)pid)); - if (!cleanup_te) { + if (parent->cleanup_te == NULL) { /* call the cleanup timer, but not too often */ int cleanup_time = lp_parm_int(-1, "smbd", "cleanuptime", 20); - cleanup_te = event_add_timed(ev_ctx, NULL, + parent->cleanup_te = tevent_add_timer(parent->ev_ctx, + parent, timeval_current_ofs(cleanup_time, 0), cleanup_timeout_fn, - &cleanup_te); + parent); DEBUG(1,("Scheduled cleanup of brl and lock database after unclean shutdown\n")); } } - child_id = procid_self(); /* Just initialize pid and potentially vnn */ - child_id.pid = pid; + child_id = pid_to_procid(pid); if (!serverid_deregister(child_id)) { DEBUG(1, ("Could not remove pid %d from serverid.tdb\n", (int)pid)); } - for (child = children; child != NULL; child = child->next) { + for (child = parent->children; child != NULL; child = child->next) { if (child->pid == pid) { - struct child_pid *tmp = child; - DLIST_REMOVE(children, child); - SAFE_FREE(tmp); - num_children -= 1; + struct smbd_child_pid *tmp = child; + DLIST_REMOVE(parent->children, child); + TALLOC_FREE(tmp); + parent->num_children -= 1; return; } } @@ -299,14 +325,14 @@ static void remove_child_pid(struct tevent_context *ev_ctx, Have we reached the process limit ? ****************************************************************************/ -static bool allowable_number_of_smbd_processes(void) +static bool allowable_number_of_smbd_processes(struct smbd_parent_context *parent) { int max_processes = lp_max_smbd_processes(); if (!max_processes) return True; - return num_children < max_processes; + return parent->num_children < max_processes; } static void smbd_sig_chld_handler(struct tevent_context *ev, @@ -318,6 +344,9 @@ static void smbd_sig_chld_handler(struct tevent_context *ev, { pid_t pid; int status; + struct smbd_parent_context *parent = + talloc_get_type_abort(private_data, + struct smbd_parent_context); while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) { bool unclean_shutdown = False; @@ -335,41 +364,24 @@ static void smbd_sig_chld_handler(struct tevent_context *ev, if (WIFSIGNALED(status)) { unclean_shutdown = True; } - remove_child_pid(ev, pid, unclean_shutdown); + remove_child_pid(parent, pid, unclean_shutdown); } } -static void smbd_setup_sig_chld_handler(struct tevent_context *ev_ctx) +static void smbd_setup_sig_chld_handler(struct smbd_parent_context *parent) { struct tevent_signal *se; - se = tevent_add_signal(ev_ctx, - ev_ctx, /* mem_ctx */ + se = tevent_add_signal(parent->ev_ctx, + parent, /* mem_ctx */ SIGCHLD, 0, smbd_sig_chld_handler, - NULL); + parent); if (!se) { exit_server("failed to setup SIGCHLD handler"); } } -struct smbd_open_socket; - -struct smbd_parent_context { - bool interactive; - - /* the list of listening sockets */ - struct smbd_open_socket *sockets; -}; - -struct smbd_open_socket { - struct smbd_open_socket *prev, *next; - struct smbd_parent_context *parent; - int fd; - struct tevent_fd *fde; - struct messaging_context *msg_ctx; -}; - static void smbd_open_socket_close_fn(struct tevent_context *ev, struct tevent_fd *fde, int fd, @@ -386,8 +398,8 @@ static void smbd_accept_connection(struct tevent_context *ev, { struct smbd_open_socket *s = talloc_get_type_abort(private_data, struct smbd_open_socket); - struct messaging_context *msg_ctx = s->msg_ctx; - struct smbd_server_connection *sconn = msg_ctx_to_sconn(msg_ctx); + struct messaging_context *msg_ctx = s->parent->msg_ctx; + struct smbd_server_connection *sconn = smbd_server_conn; struct sockaddr_storage addr; socklen_t in_addrlen = sizeof(addr); int fd; @@ -411,7 +423,7 @@ static void smbd_accept_connection(struct tevent_context *ev, return; } - if (!allowable_number_of_smbd_processes()) { + if (!allowable_number_of_smbd_processes(s->parent)) { close(fd); sconn->sock = -1; return; @@ -428,7 +440,14 @@ static void smbd_accept_connection(struct tevent_context *ev, NTSTATUS status = NT_STATUS_OK; /* Child code ... */ - am_parent = 0; + am_parent = NULL; + + /* + * Can't use TALLOC_FREE here. Nulling out the argument to it + * would overwrite memory we've just freed. + */ + talloc_free(s->parent); + s = NULL; set_my_unique_id(unique_id); @@ -442,16 +461,8 @@ static void smbd_accept_connection(struct tevent_context *ev, close_low_fds(False); /* Don't close stderr */ } - /* - * Can't use TALLOC_FREE here. Nulling out the argument to it - * would overwrite memory we've just freed. - */ - talloc_free(s->parent); - s = NULL; - status = reinit_after_fork(msg_ctx, ev, - procid_self(), true); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, @@ -473,11 +484,10 @@ static void smbd_accept_connection(struct tevent_context *ev, smb_panic("reinit_after_fork() failed"); } - smbd_setup_sig_term_handler(); - smbd_setup_sig_hup_handler(ev, - msg_ctx); + smbd_setup_sig_term_handler(sconn); + smbd_setup_sig_hup_handler(sconn); - if (!serverid_register(procid_self(), + if (!serverid_register(messaging_server_id(msg_ctx), FLAG_MSG_GENERAL|FLAG_MSG_SMBD |FLAG_MSG_DBWRAP |FLAG_MSG_PRINT_GENERAL)) { @@ -509,7 +519,7 @@ static void smbd_accept_connection(struct tevent_context *ev, sconn->sock = -1; if (pid != 0) { - add_child_pid(pid); + add_child_pid(s->parent, pid); } /* Force parent to check log size after @@ -574,7 +584,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent, return false; } - s->msg_ctx = msg_ctx; s->fde = tevent_add_fd(ev_ctx, s, s->fd, TEVENT_FD_READ, @@ -614,7 +623,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, #endif /* Stop zombies */ - smbd_setup_sig_chld_handler(ev_ctx); + smbd_setup_sig_chld_handler(parent); /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { @@ -737,7 +746,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, operations until it has gone thru a full startup, which includes checking to see that smbd is listening. */ - if (!serverid_register(procid_self(), + if (!serverid_register(messaging_server_id(msg_ctx), FLAG_MSG_GENERAL|FLAG_MSG_SMBD |FLAG_MSG_PRINT_GENERAL |FLAG_MSG_DBWRAP)) { @@ -748,10 +757,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, /* Listen to messages */ - messaging_register(msg_ctx, NULL, MSG_SMB_SAM_SYNC, msg_sam_sync); messaging_register(msg_ctx, NULL, MSG_SHUTDOWN, msg_exit_server); - messaging_register(msg_ctx, NULL, MSG_SMB_FILE_RENAME, - msg_file_was_renamed); messaging_register(msg_ctx, ev_ctx, MSG_SMB_CONF_UPDATED, smb_conf_updated); messaging_register(msg_ctx, NULL, MSG_SMB_STAT_CACHE_DELETE, @@ -836,6 +842,34 @@ static bool init_structs(void ) return True; } +static void smbd_parent_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + exit_server_cleanly("termination signal"); +} + +static void smbd_parent_sig_hup_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct smbd_parent_context *parent = + talloc_get_type_abort(private_data, + struct smbd_parent_context); + + change_to_root_user(); + DEBUG(1,("parent: Reloading services after SIGHUP\n")); + reload_services(parent->msg_ctx, -1, false); + + printing_subsystem_update(parent->ev_ctx, parent->msg_ctx, true); +} + /**************************************************************************** main program. ****************************************************************************/ @@ -886,6 +920,7 @@ extern void build_options(bool screen); uint64_t unique_id; struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; + struct tevent_signal *se; /* * Do this before any other talloc operation @@ -1120,7 +1155,7 @@ extern void build_options(bool screen); status = reinit_after_fork(msg_ctx, ev_ctx, - procid_self(), false); + false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); @@ -1128,9 +1163,31 @@ extern void build_options(bool screen); smbd_server_conn->msg_ctx = msg_ctx; - smbd_setup_sig_term_handler(); - smbd_setup_sig_hup_handler(ev_ctx, - msg_ctx); + parent = talloc_zero(ev_ctx, struct smbd_parent_context); + if (!parent) { + exit_server("talloc(struct smbd_parent_context) failed"); + } + parent->interactive = interactive; + parent->ev_ctx = ev_ctx; + parent->msg_ctx = msg_ctx; + am_parent = parent; + + se = tevent_add_signal(parent->ev_ctx, + parent, + SIGTERM, 0, + smbd_parent_sig_term_handler, + parent); + if (!se) { + exit_server("failed to setup SIGTERM handler"); + } + se = tevent_add_signal(parent->ev_ctx, + parent, + SIGHUP, 0, + smbd_parent_sig_hup_handler, + parent); + if (!se) { + exit_server("failed to setup SIGHUP handler"); + } /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ @@ -1278,7 +1335,7 @@ extern void build_options(bool screen); #endif /* Stop zombies */ - smbd_setup_sig_chld_handler(ev_ctx); + smbd_setup_sig_chld_handler(parent); smbd_process(ev_ctx, smbd_server_conn); @@ -1286,12 +1343,6 @@ extern void build_options(bool screen); return(0); } - parent = talloc_zero(ev_ctx, struct smbd_parent_context); - if (!parent) { - exit_server("talloc(struct smbd_parent_context) failed"); - } - parent->interactive = interactive; - if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports)) exit_server("open_sockets_smbd() failed");