r3356: in the standard process model we need to make sure we close all
authorAndrew Tridgell <tridge@samba.org>
Fri, 29 Oct 2004 07:00:14 +0000 (07:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:00 +0000 (13:05 -0500)
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().
(This used to be commit f2a9bbc317ba86ebe87c3ca27a3a0192de91014d)

source4/lib/socket/socket.c
source4/smbd/process_standard.c
source4/smbd/service.c

index dbbae5ea7e7341fa278c95da3d1cc90376244a00..892695f6eb92be26ef40a33729b1613cce8bb894 100644 (file)
@@ -260,6 +260,28 @@ int socket_get_fd(struct socket_context *sock)
        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 || 
index 106be7792549496ecfa2c4e523cc8e0913ab53c7..9b5547ce5403733db515000b39092aff71379929 100644 (file)
@@ -34,7 +34,8 @@ static void standard_model_startup(void)
 /*
   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 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
        /* 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) {
index ac46992261a9db2a298923a7d0c0d4b834258af3..ca5f5e75316ca97db009147a14a24a0c74cf6091 100644 (file)
@@ -77,6 +77,8 @@ struct server_context *server_service_startup(const char *model)
                
                /* 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 @@ BOOL server_service_init(void)
        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;
+               }
+       }
+}