r4943: Smplified the events handling code a lot. The first source of
authorAndrew Tridgell <tridge@samba.org>
Sun, 23 Jan 2005 11:49:15 +0000 (11:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:08 +0000 (13:09 -0500)
complexity was that events didn't automatically cleanup
themselves. This was because the events code was written before we had
talloc destructors, so you needed to call event_remove_XX() to clean
the event out of the event lists from every piece of code that used
events. I have now added automatic event destructors, which in turn
allowed me to simplify a lot of the calling code.

The 2nd source of complexity was caused by the ref_count, which was
needed to cope with event handlers destroying events while handling
them, which meant the linked lists became invalid, so the ref_count ws
used to mark events for later destruction.

The new system is much simpler. I now have a ev->destruction_count,
which is incremented in all event destructors. The event dispatch code
checks for changes to this and handles it.
(This used to be commit a3c7417cfeab429ffb22d5546b205818f531a7b4)

source4/include/events.h
source4/lib/events.c
source4/lib/messaging/messaging.c
source4/libcli/nbt/nbtsocket.c
source4/libcli/raw/clisocket.c
source4/libcli/raw/clitransport.c
source4/libcli/resolve/host.c
source4/ntvfs/posix/pvfs_wait.c
source4/rpc_server/echo/rpc_echo.c
source4/smbd/service.c

index ae18bd8bc45779a96bddf6438bf0cf88f2b03012..51a78306bb07a00c3fe796cc174ef239a2b72693 100644 (file)
 struct event_context { 
        /* list of filedescriptor events */
        struct fd_event {
+               struct event_context *event_ctx;
                struct fd_event *next, *prev;
                int fd;
                uint16_t flags; /* see EVENT_FD_* flags */
                void (*handler)(struct event_context *ev, struct fd_event *fde, 
                                struct timeval t, uint16_t flags);
                void *private;
-               int ref_count;
        } *fd_events;
 
        /* list of timed events */
        struct timed_event {
+               struct event_context *event_ctx;
                struct timed_event *next, *prev;
                struct timeval next_event;
                void (*handler)(struct event_context *ev, struct timed_event *te, 
                                struct timeval t);
                void *private;
-               int ref_count;
        } *timed_events;
 
        /* list of loop events - called on each select() */
        struct loop_event {
+               struct event_context *event_ctx;
                struct loop_event *next, *prev;
                void (*handler)(struct event_context *ev, struct loop_event *le, 
                                struct timeval t);
                void *private;
-               int ref_count;
        } *loop_events;
 
        /* list of signal events */
        struct signal_event {
+               struct event_context *event_ctx;
                struct signal_event *next, *prev;
                int signum;
                void (*handler)(struct event_context *ev, struct signal_event *se, int signum, void *sigarg);
                void *private;
-               int ref_count;
        } *signal_events;
 
        /* the maximum file descriptor number in fd_events */
@@ -74,6 +74,13 @@ struct event_context {
        /* This is the talloc parent for all concrete event structures in this
         * event context. This makes merging easy. */
        void *events;
+
+       /* this is changed by the destructors for any event type. It
+          is used to detect event destruction by event handlers,
+          which means the code that is calling all event handles
+          needs to assume that the linked list is no longer valid 
+       */
+       uint32_t destruction_count;
 };
 
 
index 54ec4ef9277b50dca2b81424701f83cf9d3fb6ce..6f0bdb4fdd8256b1dd9f7d105b915ab3ef8af1b0 100644 (file)
@@ -104,8 +104,7 @@ static void calc_maxfd(struct event_context *ev)
        struct fd_event *e;
        ev->maxfd = 0;
        for (e=ev->fd_events; e; e=e->next) {
-               if (e->ref_count && 
-                   e->fd > ev->maxfd) {
+               if (e->fd > ev->maxfd) {
                        ev->maxfd = e->fd;
                }
        }
@@ -117,7 +116,8 @@ static void calc_maxfd(struct event_context *ev)
 
   this is used by modules that need to call on the events of a lower module
 */
-struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2)
+struct event_context *event_context_merge(struct event_context *ev, 
+                                         struct event_context *ev2)
 {
        DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *);
        DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *);
@@ -136,29 +136,42 @@ struct event_context *event_context_merge(struct event_context *ev, struct event
        return ev;
 }
 
+/* to mark the ev->maxfd invalid
+ * this means we need to recalculate it
+ */
+#define EVENT_INVALID_MAXFD (-1)
+
+
+static int event_fd_destructor(void *ptr)
+{
+       struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
+       if (fde->event_ctx->maxfd == fde->fd) {
+               fde->event_ctx->maxfd = EVENT_INVALID_MAXFD;
+       }
+       DLIST_REMOVE(fde->event_ctx->fd_events, fde);
+       fde->event_ctx->destruction_count++;
+       return 0;
+}
 
 /*
   add a fd based event
   return NULL on failure (memory allocation error)
 */
-struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) 
+struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0
 {
-       e = talloc_memdup(ev->events, e, sizeof(*e));
+       struct fd_event *e = talloc(ev->events, struct fd_event);
        if (!e) return NULL;
+       *e = *e0;
        DLIST_ADD(ev->fd_events, e);
-       e->ref_count = 1;
+       e->event_ctx = ev;
        if (e->fd > ev->maxfd) {
                ev->maxfd = e->fd;
        }
+       talloc_set_destructor(e, event_fd_destructor);
        return e;
 }
 
 
-/* to mark the ev->maxfd invalid
- * this means we need to recalculate it
- */
-#define EVENT_INVALID_MAXFD (-1)
-
 /*
   remove a fd based event
   the event to remove is matched by looking at the handler
@@ -167,16 +180,8 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e)
 */
 BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
 {
-       struct fd_event *e;
-       for (e=ev->fd_events; e; e=e->next) {
-               if (e->ref_count &&
-                   e->fd == e1->fd && 
-                   e->handler == e1->handler) {
-                       e->ref_count--;
-                       return True;
-               }
-       }
-       return False;
+       talloc_free(e1);
+       return True;
 }
 
 /*
@@ -184,10 +189,13 @@ BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
 */
 void event_remove_fd_all(struct event_context *ev, int fd)
 {
-       struct fd_event *e;
-       for (e=ev->fd_events; e; e=e->next) {
-               if (e->ref_count && e->fd == fd) {
-                       e->ref_count--;
+       struct fd_event *e = ev->fd_events;
+       /* be careful to cope with extra reference counts on events */
+       while (e) {
+               if (talloc_free(ev->fd_events) == 0) {
+                       e = ev->fd_events;
+               } else {
+                       e = e->next;
                }
        }
 }
@@ -197,26 +205,35 @@ void event_remove_fd_all(struct event_context *ev, int fd)
 */
 void event_remove_fd_all_handler(struct event_context *ev, void *handler)
 {
-       struct fd_event *e;
-       for (e=ev->fd_events; e; e=e->next) {
-               if (e->ref_count &&
-                   handler == (void *)e->handler) {
-                       e->ref_count--;
+       struct fd_event *e, *next;
+       for (e=ev->fd_events; e; e=next) {
+               next = e->next;
+               if (handler == (void *)e->handler) {
+                       talloc_free(e);
                }
        }
 }
 
+static int event_timed_destructor(void *ptr)
+{
+       struct timed_event *te = talloc_get_type(ptr, struct timed_event);
+       DLIST_REMOVE(te->event_ctx->timed_events, te);
+       te->event_ctx->destruction_count++;
+       return 0;
+}
 
 /*
   add a timed event
   return NULL on failure (memory allocation error)
 */
-struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) 
+struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0
 {
-       e = talloc_memdup(ev->events, e, sizeof(*e));
+       struct timed_event *e = talloc(ev->events, struct timed_event);
        if (!e) return NULL;
-       e->ref_count = 1;
+       *e = *e0;
+       e->event_ctx = ev;
        DLIST_ADD(ev->timed_events, e);
+       talloc_set_destructor(e, event_timed_destructor);
        return e;
 }
 
@@ -224,28 +241,32 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event
   remove a timed event
   return False on failure (event not found)
 */
-BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1
+BOOL event_remove_timed(struct event_context *ev, struct timed_event *e) 
 {
-       struct timed_event *e;
-       for (e=ev->timed_events; e; e=e->next) {
-               if (e->ref_count && e == e1) {
-                       e->ref_count--;
-                       return True;
-               }
-       }
-       return False;
+       talloc_free(e);
+       return True;
+}
+
+static int event_loop_destructor(void *ptr)
+{
+       struct loop_event *le = talloc_get_type(ptr, struct loop_event);
+       DLIST_REMOVE(le->event_ctx->loop_events, le);
+       le->event_ctx->destruction_count++;
+       return 0;
 }
 
 /*
   add a loop event
   return NULL on failure (memory allocation error)
 */
-struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e)
+struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0)
 {
-       e = talloc_memdup(ev->events, e, sizeof(*e));
+       struct loop_event *e = talloc(ev->events, struct loop_event);
        if (!e) return NULL;
-       e->ref_count = 1;
+       *e = *e0;
+       e->event_ctx = ev;
        DLIST_ADD(ev->loop_events, e);
+       talloc_set_destructor(e, event_loop_destructor);
        return e;
 }
 
@@ -254,17 +275,10 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e
   the event to remove is matched only on the handler function
   return False on failure (memory allocation error)
 */
-BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1
+BOOL event_remove_loop(struct event_context *ev, struct loop_event *e) 
 {
-       struct loop_event *e;
-       for (e=ev->loop_events; e; e=e->next) {
-               if (e->ref_count &&
-                   e->handler == e1->handler) {
-                       e->ref_count--;
-                       return True;
-               }
-       }
-       return False;
+       talloc_free(e);
+       return True;
 }
 
 
@@ -288,6 +302,7 @@ int event_loop_once(struct event_context *ev)
        struct timed_event *te;
        int selrtn;
        struct timeval tval, t;
+       uint32_t destruction_count = ev->destruction_count;
 
        t = timeval_current();
 
@@ -295,14 +310,8 @@ int event_loop_once(struct event_context *ev)
           event to remove itself */
        for (le=ev->loop_events;le;) {
                struct loop_event *next = le->next;
-               if (le->ref_count == 0) {
-                       DLIST_REMOVE(ev->loop_events, le);
-                       talloc_free(le);
-               } else {
-                       le->ref_count++;
-                       le->handler(ev, le, t);
-                       le->ref_count--;
-               }
+               le->handler(ev, le, t);
+               if (destruction_count != ev->destruction_count) break;
                le = next;
        }
 
@@ -312,19 +321,11 @@ int event_loop_once(struct event_context *ev)
        /* setup any fd events */
        for (fe=ev->fd_events; fe; ) {
                struct fd_event *next = fe->next;
-               if (fe->ref_count == 0) {
-                       DLIST_REMOVE(ev->fd_events, fe);
-                       if (ev->maxfd == fe->fd) {
-                               ev->maxfd = EVENT_INVALID_MAXFD;
-                       }
-                       talloc_free(fe);
-               } else {
-                       if (fe->flags & EVENT_FD_READ) {
-                               FD_SET(fe->fd, &r_fds);
-                       }
-                       if (fe->flags & EVENT_FD_WRITE) {
-                               FD_SET(fe->fd, &w_fds);
-                       }
+               if (fe->flags & EVENT_FD_READ) {
+                       FD_SET(fe->fd, &r_fds);
+               }
+               if (fe->flags & EVENT_FD_WRITE) {
+                       FD_SET(fe->fd, &w_fds);
                }
                fe = next;
        }
@@ -379,10 +380,11 @@ int event_loop_once(struct event_context *ev)
                                uint16_t flags = 0;
                                if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
                                if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
-                               if (fe->ref_count && flags) {
-                                       fe->ref_count++;
+                               if (flags) {
                                        fe->handler(ev, fe, t, flags);
-                                       fe->ref_count--;
+                                       if (destruction_count != ev->destruction_count) {
+                                               break;
+                                       }
                                }
                        }
                }
@@ -391,13 +393,11 @@ int event_loop_once(struct event_context *ev)
        /* call any timed events that are now due */
        for (te=ev->timed_events;te;) {
                struct timed_event *next = te->next;
-               if (te->ref_count == 0) {
-                       DLIST_REMOVE(ev->timed_events, te);
-                       talloc_free(te);
-               } else if (timeval_compare(&te->next_event, &t) >= 0) {
-                       te->ref_count++;
+               if (timeval_compare(&te->next_event, &t) >= 0) {
                        te->handler(ev, te, t);
-                       te->ref_count--;
+                       if (destruction_count != ev->destruction_count) {
+                               break;
+                       }
                        if (timeval_compare(&te->next_event, &t) >= 0) {
                                /* the handler didn't set a time for the 
                                   next event - remove the event */
index 84c9adc874e0558eb8ade47c374ac313cd3c4a1c..beceb342c9f19aab74de67915e434767991598a5 100644 (file)
@@ -188,17 +188,6 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd
        }
 }
 
-/*
-  destroy a messaging record
-*/
-static int rec_destructor(void *ptr)
-{
-       struct messaging_rec *rec = ptr;
-       struct messaging_context *msg = rec->msg;
-       event_remove_fd(msg->event.ev, rec->fde);
-       return 0;
-}
-
 /*
   handle a new incoming connection
 */
@@ -233,7 +222,7 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event *
 
        rec->fde        = event_add_fd(msg->event.ev, &fde2);
 
-       talloc_set_destructor(rec, rec_destructor);
+       talloc_steal(rec, rec->fde);
 }
 
 /*
@@ -370,8 +359,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve
        fde.handler     = messaging_send_handler;
 
        rec->fde        = event_add_fd(msg->event.ev, &fde);
-
-       talloc_set_destructor(rec, rec_destructor);
+       talloc_steal(rec, rec->fde);
 
        messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
 }
@@ -435,8 +423,7 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t
        fde.handler     = messaging_send_handler;
 
        rec->fde        = event_add_fd(msg->event.ev, &fde);
-
-       talloc_set_destructor(rec, rec_destructor);
+       talloc_steal(rec, rec->fde);
 
        messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
 
@@ -464,7 +451,6 @@ NTSTATUS messaging_send_ptr(struct messaging_context *msg, servid_t server,
 static int messaging_destructor(void *ptr)
 {
        struct messaging_context *msg = ptr;
-       event_remove_fd(msg->event.ev, msg->event.fde);
        unlink(msg->path);
        return 0;
 }
@@ -516,6 +502,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, servid_t server_id
 
        msg->event.ev   = talloc_reference(msg,ev);
        msg->event.fde  = event_add_fd(ev, &fde);
+       talloc_steal(msg, msg->event.fde);
 
        talloc_set_destructor(msg, messaging_destructor);
        
index 664e6fdce0b8d3538a80e8b644026a018f2b5b47..d970f8e4e022feb6cceb38e0c786c6b3984c12be 100644 (file)
 #define NBT_MAX_PACKET_SIZE 2048
 #define NBT_MAX_REPLIES 1000
 
-/*
-  destroy a nbt socket
-*/
-static int nbtsock_destructor(void *ptr)
-{
-       struct nbt_name_socket *nbtsock = talloc_get_type(ptr, struct nbt_name_socket);
-       event_remove_fd(nbtsock->event_ctx, nbtsock->fde);
-       return 0;
-}
-
 /*
   destroy a pending request
 */
@@ -56,7 +46,6 @@ static int nbt_name_request_destructor(void *ptr)
                req->request->name_trn_id = 0;
        }
        if (req->te) {
-               event_remove_timed(req->nbtsock->event_ctx, req->te);
                req->te = NULL;
        }
        if (req->nbtsock->send_queue == NULL) {
@@ -279,7 +268,7 @@ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
        fde.private = nbtsock;
        nbtsock->fde = event_add_fd(nbtsock->event_ctx, &fde);
 
-       talloc_set_destructor(nbtsock, nbtsock_destructor);
+       talloc_steal(nbtsock, nbtsock->fde);
        
        return nbtsock;
 
@@ -356,6 +345,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
        te.handler = nbt_name_socket_timeout;
        te.private = req;
        req->te = event_add_timed(nbtsock->event_ctx, &te);
+       talloc_steal(req, req->te);
        
        talloc_set_destructor(req, nbt_name_request_destructor);        
 
index 9249f453e880360e90996f1546f0c63b22bd79b5..847f5c1b0ac598ac8ed0ee1c337e75ae4d162d38 100644 (file)
@@ -37,16 +37,6 @@ struct clisocket_connect {
 };
 
 
-static int smbcli_sock_destructor(void *ptr)
-{
-       struct smbcli_socket *sock = talloc_get_type(ptr, struct smbcli_socket);
-
-       if (sock->event.fde && sock->event.ctx) {
-               event_remove_fd(sock->event.ctx, sock->event.fde);
-       }
-       return 0;
-}
-
 /*
   create a smbcli_socket context
   The event_ctx is optional - if not supplied one will be created
@@ -71,8 +61,6 @@ struct smbcli_socket *smbcli_sock_init(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       talloc_set_destructor(sock, smbcli_sock_destructor);
-
        return sock;
 }
 
@@ -134,11 +122,7 @@ static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock,
                talloc_free(sock->sock);
                sock->sock = NULL;
        }
-
-       if (sock->event.fde) {
-               event_remove_fd(sock->event.ctx, sock->event.fde);
-               sock->event.fde = NULL;
-       }
+       talloc_free(sock->event.fde);
 
        status = socket_create("ip", SOCKET_TYPE_STREAM, &sock->sock, 0);
        if (!NT_STATUS_IS_OK(status)) {
@@ -155,6 +139,8 @@ static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock,
        fde.private = sock;
 
        sock->event.fde = event_add_fd(sock->event.ctx, &fde);
+       talloc_steal(sock, sock->event.fde);
+
        sock->port = port;
        set_blocking(fde.fd, False);
 
index 918f18fa4069de2b467d62a46e8330ef6a55260e..b053b362ca5528a6ed04bf697ee0436febe52fbd 100644 (file)
@@ -55,7 +55,6 @@ static int transport_destructor(void *ptr)
        struct smbcli_transport *transport = ptr;
 
        smbcli_transport_dead(transport);
-       event_remove_timed(transport->socket->event.ctx, transport->socket->event.te);
        return 0;
 }
 
@@ -323,6 +322,7 @@ void smbcli_transport_idle_handler(struct smbcli_transport *transport,
        te.handler = idle_handler;
        te.private = transport;
        transport->socket->event.te = event_add_timed(transport->socket->event.ctx, &te);
+       talloc_steal(transport, transport->socket->event.te);
 }
 
 /*
index 2cc0c1705f3e1c9bb8e7e28e6659eee4b9403a65..b9aa1aa2728976aa440bd9cb99a67d72641fd29f 100644 (file)
@@ -57,9 +57,6 @@ static int host_destructor(void *ptr)
        if (state->child != (pid_t)-1) {
                kill(state->child, SIGTERM);
        }
-       if (state->fde) {
-               event_remove_fd(state->event_ctx, state->fde);
-       }
        return 0;
 }
 
@@ -174,6 +171,7 @@ struct smbcli_composite *resolve_name_host_send(struct nbt_name *name,
                close(fd[1]);
                goto failed;
        }
+       talloc_steal(state, state->fde);
 
        /* signal handling in posix really sucks - doing this in a library
           affects the whole app, but what else to do?? */
index 4b757e0be10f209ab446b5304aa8e2c55723e642..e4175ca8ccaf9f277b833dd93d1832d5aad11a9c 100644 (file)
@@ -105,7 +105,6 @@ static int pvfs_wait_destructor(void *ptr)
 {
        struct pvfs_wait *pwait = ptr;
        messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
-       event_remove_timed(pwait->ev, pwait->te);
        DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
        return 0;
 }
@@ -145,6 +144,7 @@ static int pvfs_wait_destructor(void *ptr)
        te.handler = pvfs_wait_timeout;
        te.private = pwait;
        pwait->te = event_add_timed(pwait->ev, &te);
+       talloc_steal(pwait, pwait->te);
 
        /* register with the messaging subsystem for this message
           type */
index 164e2d588f8712a529a6bd1467af3408cebfa50f..2b4f31482d3a2b3221e9dbb7bde568921f4cfeae 100644 (file)
@@ -135,13 +135,6 @@ static void echo_TestSleep_handler(struct event_context *ev, struct timed_event
        }
 }
 
-static int echo_TestSleep_destructor(void *ptr)
-{
-       struct echo_TestSleep_private *p = ptr;
-       event_remove_timed(p->dce_call->event_ctx, p->te);
-       return 0;
-}
-
 static long echo_TestSleep(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestSleep *r)
 {
        struct timed_event te;
@@ -170,8 +163,7 @@ static long echo_TestSleep(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_c
        if (!p->te) {
                return 0;
        }
-
-       talloc_set_destructor(p, echo_TestSleep_destructor);
+       talloc_steal(p, p->te);
 
        dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
        return 0;
index 40a2a4b50657066fc16ea33a3a82f2f5c90c2548..7067a26e7a478001ad69072e170100d452c8ea61 100644 (file)
@@ -171,6 +171,7 @@ struct server_stream_socket *service_setup_stream_socket(struct server_service *
        }
 
        talloc_steal(stream_socket, sock);
+       talloc_steal(stream_socket, stream_socket->event.fde);
 
        if (stream_socket->stream.ops->socket_init) {
                stream_socket->stream.ops->socket_init(stream_socket);
@@ -194,15 +195,6 @@ static int server_connection_destructor(void *ptr)
                conn->stream_socket->stream.ops->close_connection(conn, "shutdown");
         }
 
-       if (conn->event.fde) {
-               event_remove_fd(conn->event.ctx, conn->event.fde);
-               conn->event.fde = NULL;
-       }
-       if (conn->event.idle) {
-               event_remove_timed(conn->event.ctx, conn->event.idle);
-               conn->event.idle = NULL;
-       }
-
        return 0;
 }
 
@@ -250,6 +242,9 @@ struct server_connection *server_setup_connection(struct event_context *ev,
        srv_conn->event.fde     = event_add_fd(ev,&fde);
        srv_conn->event.idle    = event_add_timed(ev,&idle);
 
+       talloc_steal(srv_conn, srv_conn->event.fde);
+       talloc_steal(srv_conn, srv_conn->event.idle);
+
        talloc_set_destructor(srv_conn, server_connection_destructor);
 
        if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {