diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/include/events.h | 15 | ||||
-rw-r--r-- | source4/lib/events.c | 170 | ||||
-rw-r--r-- | source4/lib/messaging/messaging.c | 21 | ||||
-rw-r--r-- | source4/libcli/nbt/nbtsocket.c | 14 | ||||
-rw-r--r-- | source4/libcli/raw/clisocket.c | 20 | ||||
-rw-r--r-- | source4/libcli/raw/clitransport.c | 2 | ||||
-rw-r--r-- | source4/libcli/resolve/host.c | 4 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_wait.c | 2 | ||||
-rw-r--r-- | source4/rpc_server/echo/rpc_echo.c | 10 | ||||
-rw-r--r-- | source4/smbd/service.c | 13 |
10 files changed, 113 insertions, 158 deletions
diff --git a/source4/include/events.h b/source4/include/events.h index ae18bd8bc4..51a78306bb 100644 --- a/source4/include/events.h +++ b/source4/include/events.h @@ -25,41 +25,41 @@ 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; }; diff --git a/source4/lib/events.c b/source4/lib/events.c index 54ec4ef927..6f0bdb4fdd 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -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 */ diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 84c9adc874..beceb342c9 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -189,17 +189,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 */ static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, @@ -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); diff --git a/source4/libcli/nbt/nbtsocket.c b/source4/libcli/nbt/nbtsocket.c index 664e6fdce0..d970f8e4e0 100644 --- a/source4/libcli/nbt/nbtsocket.c +++ b/source4/libcli/nbt/nbtsocket.c @@ -29,16 +29,6 @@ #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 */ static int nbt_name_request_destructor(void *ptr) @@ -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); diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index 9249f453e8..847f5c1b0a 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -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); diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index 918f18fa40..b053b362ca 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -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); } /* diff --git a/source4/libcli/resolve/host.c b/source4/libcli/resolve/host.c index 2cc0c1705f..b9aa1aa272 100644 --- a/source4/libcli/resolve/host.c +++ b/source4/libcli/resolve/host.c @@ -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?? */ diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c index 4b757e0be1..e4175ca8cc 100644 --- a/source4/ntvfs/posix/pvfs_wait.c +++ b/source4/ntvfs/posix/pvfs_wait.c @@ -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 */ diff --git a/source4/rpc_server/echo/rpc_echo.c b/source4/rpc_server/echo/rpc_echo.c index 164e2d588f..2b4f31482d 100644 --- a/source4/rpc_server/echo/rpc_echo.c +++ b/source4/rpc_server/echo/rpc_echo.c @@ -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; diff --git a/source4/smbd/service.c b/source4/smbd/service.c index 40a2a4b506..7067a26e7a 100644 --- a/source4/smbd/service.c +++ b/source4/smbd/service.c @@ -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))) { |