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 */
/* 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;
};
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;
}
}
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 *);
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
*/
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;
}
/*
*/
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;
}
}
}
*/
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;
}
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;
}
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;
}
struct timed_event *te;
int selrtn;
struct timeval tval, t;
+ uint32_t destruction_count = ev->destruction_count;
t = timeval_current();
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;
}
/* 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;
}
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;
+ }
}
}
}
/* 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 */
}
}
-/*
- 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
*/
rec->fde = event_add_fd(msg->event.ev, &fde2);
- talloc_set_destructor(rec, rec_destructor);
+ talloc_steal(rec, rec->fde);
}
/*
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);
}
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);
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;
}
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);
#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
*/
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) {
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;
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);
};
-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
return NULL;
}
- talloc_set_destructor(sock, smbcli_sock_destructor);
-
return 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)) {
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);
struct smbcli_transport *transport = ptr;
smbcli_transport_dead(transport);
- event_remove_timed(transport->socket->event.ctx, transport->socket->event.te);
return 0;
}
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);
}
/*
if (state->child != (pid_t)-1) {
kill(state->child, SIGTERM);
}
- if (state->fde) {
- event_remove_fd(state->event_ctx, state->fde);
- }
return 0;
}
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?? */
{
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;
}
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 */
}
}
-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;
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;
}
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);
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;
}
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))) {