summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/events.h15
-rw-r--r--source4/lib/events.c170
-rw-r--r--source4/lib/messaging/messaging.c21
-rw-r--r--source4/libcli/nbt/nbtsocket.c14
-rw-r--r--source4/libcli/raw/clisocket.c20
-rw-r--r--source4/libcli/raw/clitransport.c2
-rw-r--r--source4/libcli/resolve/host.c4
-rw-r--r--source4/ntvfs/posix/pvfs_wait.c2
-rw-r--r--source4/rpc_server/echo/rpc_echo.c10
-rw-r--r--source4/smbd/service.c13
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))) {