diff options
Diffstat (limited to 'source4/smbd/process_standard.c')
-rw-r--r-- | source4/smbd/process_standard.c | 115 |
1 files changed, 88 insertions, 27 deletions
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 3612c6a7f4..b0f7cf1a11 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -29,10 +29,16 @@ /* called when the process model is selected */ -static void standard_model_startup(void) +static void standard_model_init(struct server_context *server) { signal(SIGCHLD, SIG_IGN); - smbd_process_init(); +} + +static void standard_model_exit(struct server_context *server, const char *reason) +{ + DEBUG(1,("standard_model_exit: reason[%s]\n",reason)); + talloc_free(server); + exit(0); } /* @@ -43,12 +49,12 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event { NTSTATUS status; struct socket_context *sock; - struct server_socket *server_socket = srv_fde->private; + struct server_stream_socket *stream_socket = srv_fde->private; struct server_connection *conn; pid_t pid; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock); + status = socket_accept(stream_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); @@ -68,7 +74,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event /* Child code ... */ /* close all the listening sockets */ - service_close_listening_sockets(server_socket->service->srv_ctx); + event_remove_fd_all_handler(ev, server_accept_handler); /* we don't care if the dup fails, as its only a select() speed optimisation */ @@ -83,16 +89,15 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event set_need_random_reseed(); - conn = server_setup_connection(ev, server_socket, sock, t, getpid()); + conn = server_setup_connection(ev, stream_socket, sock, t, getpid()); if (!conn) { DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); + exit(1); return; } talloc_steal(conn, sock); - DLIST_ADD(server_socket->connection_list,conn); - /* return to the event loop */ } @@ -103,7 +108,7 @@ static void standard_terminate_connection(struct server_connection *conn, const DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason)); if (conn) { - talloc_free(conn->service->srv_ctx); + talloc_free(conn->stream_socket->service->server); } /* this init_iconv() has the effect of freeing the iconv context memory, @@ -117,38 +122,94 @@ static void standard_terminate_connection(struct server_connection *conn, const exit(0); } -static int standard_get_id(struct smbsrv_request *req) +/* + called to create a new event context for a new task +*/ +static void standard_create_task(struct server_task *task) { - return (int)req->smb_conn->pid; + pid_t pid; + + pid = fork(); + + if (pid != 0) { + /* parent or error code ... */ + talloc_free(task); + /* go back to the event loop */ + return; + } + + /* Child code ... */ + + /* close all the listening sockets */ + event_remove_fd_all_handler(task->service->server->event.ctx, server_accept_handler); + + /* tdb needs special fork handling */ + if (tdb_reopen_all() == -1) { + DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n")); + } + + /* Ensure that the forked children do not expose identical random streams */ + + set_need_random_reseed(); + + task->task.id = (uint32)getpid(); + task->event.ctx = task->service->server->event.ctx; + + /* setup to receive internal messages on this connection */ + task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx); + if (!task->messaging.ctx) { + server_terminate_task(task, "messaging_init() failed"); + return; + } + + task->task.ops->task_init(task); + + server_terminate_task(task, "exit"); + return; } -static void standard_exit_server(struct server_context *srv_ctx, const char *reason) +/* + called to destroy a new event context for a new task +*/ +static void standard_terminate_task(struct server_task *task, const char *reason) { - DEBUG(1,("standard_exit_server: reason[%s]\n",reason)); + DEBUG(2,("standard_terminate_task: reason[%s]\n",reason)); + + talloc_free(task); + + /* this init_iconv() has the effect of freeing the iconv context memory, + which makes leak checking easier */ + init_iconv(); + + /* the secrets db should really hang off the connection structure */ + secrets_shutdown(); + + /* terminate this process */ + exit(0); } +static const struct model_ops standard_ops = { + .name = "standard", + + .model_init = standard_model_init, + .model_exit = standard_model_exit, + + .accept_connection = standard_accept_connection, + .terminate_connection = standard_terminate_connection, + + .create_task = standard_create_task, + .terminate_task = standard_terminate_task +}; + /* initialise the standard process model, registering ourselves with the process model subsystem */ NTSTATUS process_model_standard_init(void) { NTSTATUS ret; - struct model_ops ops; - - ZERO_STRUCT(ops); - - /* fill in our name */ - ops.name = "standard"; - - /* fill in all the operations */ - ops.model_startup = standard_model_startup; - ops.accept_connection = standard_accept_connection; - ops.terminate_connection = standard_terminate_connection; - ops.exit_server = standard_exit_server; - ops.get_id = standard_get_id; /* register ourselves with the PROCESS_MODEL subsystem. */ - ret = register_process_model(&ops); + ret = register_process_model(&standard_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register process_model 'standard'!\n")); return ret; |