From: Alan T. DeKok Date: Mon, 19 Jun 2017 18:16:07 +0000 (-0400) Subject: export EVFILT_USER ident to caller, and pass it to control API X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1606f498e992c689fe7c72137953b8cdc39618a;p=thirdparty%2Ffreeradius-server.git export EVFILT_USER ident to caller, and pass it to control API --- diff --git a/src/include/event.h b/src/include/event.h index e2979653709..d82b3687e80 100644 --- a/src/include/event.h +++ b/src/include/event.h @@ -97,7 +97,7 @@ int fr_event_timer_insert(fr_event_list_t *el, void const *ctx, struct timeval *when, fr_event_timer_t **parent); int fr_event_timer_run(fr_event_list_t *el, struct timeval *when); -int fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2)); +uintptr_t fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2)); int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) CC_HINT(nonnull(1,2)); int fr_event_post_insert(fr_event_list_t *el, fr_event_callback_t callback, void *uctx) CC_HINT(nonnull(1,2)); diff --git a/src/lib/io/network.c b/src/lib/io/network.c index cf37f2bd60d..568e3005ecf 100644 --- a/src/lib/io/network.c +++ b/src/lib/io/network.c @@ -69,6 +69,8 @@ struct fr_network_t { fr_atomic_queue_t *aq_control; //!< atomic queue for control messages sent to me + uintptr_t aq_ident; //!< identifier for control-plane events + fr_control_t *control; //!< the control plane fr_ring_buffer_t *rb; //!< ring buffer for my control-plane messages @@ -609,7 +611,6 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger) nr = talloc_zero(ctx, fr_network_t); if (!nr) { - nomem: fr_strerror_printf("Failed allocating memory"); return NULL; } @@ -629,12 +630,22 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger) nr->aq_control = fr_atomic_queue_create(nr, 1024); if (!nr->aq_control) { talloc_free(nr); - goto nomem; + return NULL; + } + + nr->aq_ident = fr_event_user_insert(nr->el, fr_network_evfilt_user, nr); + if (!nr->aq_ident) { + fr_strerror_printf("Failed updating event list: %s", fr_strerror()); + talloc_free(nr); + return NULL; } - nr->control = fr_control_create(nr, nr->kq, nr->aq_control, 1024); + + nr->control = fr_control_create(nr, nr->kq, nr->aq_control, nr->aq_ident); if (!nr->control) { fr_strerror_printf("Failed creating control queue: %s", fr_strerror()); + fail: + (void) fr_event_user_delete(nr->el, fr_network_evfilt_user, nr); talloc_free(nr); return NULL; } @@ -642,26 +653,24 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger) nr->rb = fr_ring_buffer_create(nr, FR_CONTROL_MAX_MESSAGES * FR_CONTROL_MAX_SIZE); if (!nr->rb) { fr_strerror_printf("Failed creating ring buffer: %s", fr_strerror()); - talloc_free(nr); - return NULL; + fail2: + fr_control_free(nr->control); + goto fail; } if (fr_control_callback_add(nr->control, FR_CONTROL_ID_CHANNEL, nr, fr_network_channel_callback) < 0) { fr_strerror_printf("Failed adding channel callback: %s", fr_strerror()); - talloc_free(nr); - return NULL; + goto fail2; } if (fr_control_callback_add(nr->control, FR_CONTROL_ID_SOCKET, nr, fr_network_socket_callback) < 0) { fr_strerror_printf("Failed adding socket callback: %s", fr_strerror()); - talloc_free(nr); - return NULL; + goto fail2; } if (fr_control_callback_add(nr->control, FR_CONTROL_ID_WORKER, nr, fr_network_worker_callback) < 0) { fr_strerror_printf("Failed adding worker callback: %s", fr_strerror()); - talloc_free(nr); - return NULL; + goto fail2; } /* @@ -669,46 +678,42 @@ fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_log_t *logger) */ nr->sockets = rbtree_create(nr, socket_cmp, NULL, RBTREE_FLAG_NONE); if (!nr->sockets) { - talloc_free(nr); - goto nomem; + fr_strerror_printf("Failed creating tree for sockets: %s", fr_strerror()); + goto fail2; } nr->replies = fr_heap_create(reply_cmp, offsetof(fr_channel_data_t, channel.heap_id)); if (!nr->replies) { - talloc_free(nr); - goto nomem; + fr_strerror_printf("Failed creating heap for replies: %s", fr_strerror()); + goto fail2; } nr->workers = fr_heap_create(worker_cmp, offsetof(fr_network_worker_t, heap_id)); if (!nr->workers) { - talloc_free(nr); - goto nomem; + fr_strerror_printf("Failed creating heap for workers: %s", fr_strerror()); + fail3: + fr_heap_delete(nr->replies); + goto fail2; } nr->closing = fr_heap_create(worker_cmp, offsetof(fr_network_worker_t, heap_id)); if (!nr->closing) { - talloc_free(nr); - goto nomem; + fr_strerror_printf("Failed creating heap for exiting workers: %s", fr_strerror()); + goto fail3; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_init(&nr->mutex, NULL) != 0) { fr_strerror_printf("Failed initializing mutex"); - talloc_free(nr); - return NULL; + fail4: + fr_heap_delete(nr->closing); + goto fail3; } #endif - if (fr_event_user_insert(nr->el, fr_network_evfilt_user, nr) < 0) { - fr_strerror_printf("Failed updating event list: %s", fr_strerror()); - talloc_free(nr); - return NULL; - } - if (fr_event_post_insert(nr->el, fr_network_post_event, nr) < 0) { fr_strerror_printf("Failed inserting post-processing event"); - talloc_free(nr); - return NULL; + goto fail4; } return nr; diff --git a/src/lib/io/worker.c b/src/lib/io/worker.c index 4e2e6f82d5e..854d438861c 100644 --- a/src/lib/io/worker.c +++ b/src/lib/io/worker.c @@ -91,10 +91,12 @@ struct fr_worker_t { int kq; //!< my kq - fr_log_t *log; //!< log destination + fr_log_t *log; //!< log destination fr_atomic_queue_t *aq_control; //!< atomic queue for control messages sent to me + uintptr_t aq_ident; //!< identifier for control-plane events + fr_control_t *control; //!< the control plane fr_event_list_t *el; //!< our event list @@ -141,6 +143,7 @@ static void fr_worker_post_event(fr_event_list_t *el, struct timeval *now, void FR_DLIST_INIT(worker->_name.list); \ worker->_name.heap = fr_heap_create(_func, offsetof(_type, _member)); \ if (!worker->_name.heap) { \ + (void) fr_event_user_delete(worker->el, fr_worker_evfilt_user, worker); \ talloc_free(worker); \ goto nomem; \ } \ @@ -1064,20 +1067,29 @@ nomem: worker->aq_control = fr_atomic_queue_create(worker, 1024); if (!worker->aq_control) { + fr_strerror_printf("Failed creating atomic queue"); + fail: talloc_free(worker); - goto nomem; + return NULL; } - worker->control = fr_control_create(worker, worker->kq, worker->aq_control, 1024); + worker->aq_ident = fr_event_user_insert(worker->el, fr_worker_evfilt_user, worker); + if (!worker->aq_ident) { + fr_strerror_printf("Failed updating event list: %s", fr_strerror()); + goto fail; + } + + worker->control = fr_control_create(worker, worker->kq, worker->aq_control, worker->aq_ident); if (!worker->control) { - talloc_free(worker); - goto nomem;; + fr_strerror_printf("Failed creating control plane: %s", fr_strerror()); + fail2: + (void) fr_event_user_delete(worker->el, fr_worker_evfilt_user, worker); + goto fail; } if (fr_control_callback_add(worker->control, FR_CONTROL_ID_CHANNEL, worker, fr_worker_channel_callback) < 0) { fr_strerror_printf("Failed adding control channel: %s", fr_strerror()); - talloc_free(worker); - return NULL; + goto fail2; } WORKER_HEAP_INIT(to_decode, worker_message_cmp, fr_channel_data_t, channel.heap_id); @@ -1085,22 +1097,16 @@ nomem: worker->runnable = fr_heap_create(worker_request_cmp, offsetof(REQUEST, heap_id)); if (!worker->runnable) { - talloc_free(worker); - goto nomem;; + fr_strerror_printf("Failed creating runnable heap"); + goto fail; } FR_DLIST_INIT(worker->time_order); FR_DLIST_INIT(worker->waiting_to_die); - if (fr_event_user_insert(worker->el, fr_worker_evfilt_user, worker) < 0) { - fr_strerror_printf("Failed updating event list: %s", fr_strerror()); - talloc_free(worker); - return NULL; - } - if (fr_event_post_insert(worker->el, fr_worker_post_event, worker) < 0) { fr_strerror_printf("Failed inserting post-processing event"); - talloc_free(worker); - return NULL; + fr_heap_delerte(worker->runnable); + goto fail2; } return worker; diff --git a/src/lib/util/event.c b/src/lib/util/event.c index 41e9a79cbc1..a690da26bfc 100644 --- a/src/lib/util/event.c +++ b/src/lib/util/event.c @@ -91,6 +91,18 @@ typedef struct fr_event_post_t { void *ctx; //!< context for the callback. } fr_event_post_t; + +/** Callbacks for user events + * + */ +typedef struct fr_event_user_t { + fr_dlist_t entry; //!< linked list of callback + uintptr_t ident; //!< the identifier of this event + fr_event_user_handler_t callback; //!< the callback to call + void *ctx; //!< context for the callback. +} fr_event_user_t; + + /** Stores all information relating to an event list * */ @@ -112,9 +124,7 @@ struct fr_event_list_t { int kq; //!< instance associated with this event list. - fr_event_user_handler_t user; //!< callback for EVFILT_USER events - void *user_ctx; //!< Context pointer to pass to the user callback. - + fr_dlist_t user_callbacks; //!< EVFILT_USER callbacks fr_dlist_t post_callbacks; //!< post-processing callbacks struct kevent events[FR_EV_BATCH_FDS]; /* so it doesn't go on the stack every time */ @@ -577,38 +587,57 @@ int fr_event_timer_insert(fr_event_list_t *el, fr_event_callback_t callback, voi /** Add a user callback to the event list. * * @param[in] el containing the timer events. - * @param[in] user the callback for EVFILT_USER - * @param[in] ctx user context for the callback + * @param[in] callback the callback for EVFILT_USER + * @param[in] uctx user context for the callback * @return - * - < 0 on error - * - 0 on success + * - 0 on error + * - uintptr_t ident for EVFILT_USER signaling */ -int fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) +uintptr_t fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t callback, void *uctx) { - el->user = user; - el->user_ctx = ctx; + fr_event_user_t *user; - return 0; + user = talloc(el, fr_event_user_t); + user->callback = callback; + user->ctx = uctx; + user->ident = (uintptr_t) user; + + fr_dlist_insert_tail(&el->user_callbacks, &user->entry); + + return user->ident;; } /** Delete a user callback to the event list. * * @param[in] el containing the timer events. - * @param[in] user the callback for EVFILT_USER - * @param[in] ctx user context for the callback + * @param[in] callback the callback for EVFILT_USER + * @param[in] uctx user context for the callback * @return * - < 0 on error * - 0 on success */ -int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t user, void *ctx) +int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t callback, void *uctx) { - if ((el->user != user) || (el->user_ctx != ctx)) return -1; + fr_dlist_t *entry, *next; - el->user = NULL; - el->user_ctx = NULL; + for (entry = FR_DLIST_FIRST(el->user_callbacks); + entry != NULL; + entry = next) { + fr_event_user_t *user; - return 0; + next = FR_DLIST_NEXT(el->user_callbacks, entry); + + user = fr_ptr_to_type(fr_event_user_t, entry, entry); + if ((user->callback == callback) && + (user->ctx == uctx)) { + fr_dlist_remove(entry); + talloc_free(user); + return 0; + } + } + + return -1; } /** Add a post-event callback to the event list. @@ -825,14 +854,26 @@ void fr_event_service(fr_event_list_t *el) /* * Process any user events */ - if (el->user && (el->events[i].filter == EVFILT_USER)) { + if (el->events[i].filter == EVFILT_USER) { /* * This is just a "wakeup" event, which * is always ignored. */ if (el->events[i].ident == 0) continue; - el->user(el->kq, &el->events[i], el->user_ctx); + for (entry = FR_DLIST_FIRST(el->user_callbacks); + entry != NULL; + entry = FR_DLIST_NEXT(el->user_callbacks, entry)) { + fr_event_user_t *user; + + user = fr_ptr_to_type(fr_event_user_t, entry, entry); + + if (user->ident != el->events[i].ident) continue; + + user->callback(el->kq, &el->events[i], user->ctx); + break; + } + continue; } @@ -1037,6 +1078,7 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_t status, el->status_ctx = status_ctx; FR_DLIST_INIT(el->post_callbacks); + FR_DLIST_INIT(el->user_callbacks); /* * Set our "exit" callback as ident 0.