Author: tridge Date: 2004-10-29 07:00:14 +0000 (Fri, 29 Oct 2004) New Revision: 3356
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=3356 Log: in the standard process model we need to make sure we close all listening sockets after the fork to prevent the child still listening on incoming requests. I have also added an optimisation where we use dup()/close() to lower the file descriptor number of the new socket to the lowest possible after closing our listening sockets. This keeps the max fd num passed to select() low, which makes a difference to the speed of select(). Modified: branches/SAMBA_4_0/source/lib/socket/socket.c branches/SAMBA_4_0/source/smbd/process_standard.c branches/SAMBA_4_0/source/smbd/service.c Changeset: Modified: branches/SAMBA_4_0/source/lib/socket/socket.c =================================================================== --- branches/SAMBA_4_0/source/lib/socket/socket.c 2004-10-29 06:01:51 UTC (rev 3355) +++ branches/SAMBA_4_0/source/lib/socket/socket.c 2004-10-29 07:00:14 UTC (rev 3356) @@ -260,6 +260,28 @@ return sock->ops->get_fd(sock); } +/* + call dup() on a socket, and close the old fd. This is used to change + the fd to the lowest available number, to make select() more + efficient (select speed depends on the maxiumum fd number passed to + it) +*/ +NTSTATUS socket_dup(struct socket_context *sock) +{ + int fd; + if (sock->fd == -1) { + return NT_STATUS_INVALID_HANDLE; + } + fd = dup(sock->fd); + if (fd == -1) { + return map_nt_error_from_unix(errno); + } + close(sock->fd); + sock->fd = fd; + return NT_STATUS_OK; + +} + const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type) { if (strcmp("ip", name) == 0 || Modified: branches/SAMBA_4_0/source/smbd/process_standard.c =================================================================== --- branches/SAMBA_4_0/source/smbd/process_standard.c 2004-10-29 06:01:51 UTC (rev 3355) +++ branches/SAMBA_4_0/source/smbd/process_standard.c 2004-10-29 07:00:14 UTC (rev 3356) @@ -34,7 +34,8 @@ /* called when a listening socket becomes readable */ -static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde, time_t t, uint16_t flags) +static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde, + time_t t, uint16_t flags) { NTSTATUS status; struct socket_context *sock; @@ -63,7 +64,11 @@ /* Child code ... */ /* close all the listening sockets */ - event_remove_fd_all_handler(ev, standard_accept_connection); + service_close_listening_sockets(server_socket->service->srv_ctx); + + /* we don't care if the dup fails, as its only a select() + speed optimisation */ + socket_dup(sock); /* tdb needs special fork handling */ if (tdb_reopen_all() == -1) { Modified: branches/SAMBA_4_0/source/smbd/service.c =================================================================== --- branches/SAMBA_4_0/source/smbd/service.c 2004-10-29 06:01:51 UTC (rev 3355) +++ branches/SAMBA_4_0/source/smbd/service.c 2004-10-29 07:00:14 UTC (rev 3356) @@ -77,6 +77,8 @@ /* TODO: service_init() should return a result */ service->ops->service_init(service, model_ops); + + DLIST_ADD(srv_ctx->service_list, service); } return srv_ctx; @@ -328,3 +330,22 @@ DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION)); return True; } + + +/* + close all listening sockets. This is called by process models that fork, to + ensure that the listen sockets from the parent are closed +*/ +void service_close_listening_sockets(struct server_context *srv_ctx) +{ + struct server_service *svc; + for (svc=srv_ctx->service_list;svc;svc=svc->next) { + struct server_socket *sock; + for (sock=svc->socket_list;sock;sock=sock->next) { + event_remove_fd(sock->event.ctx, sock->event.fde); + sock->event.fde = NULL; + socket_destroy(sock->socket); + sock->socket = NULL; + } + } +}