* @copyright 2000 Jeff Carneal (jeff@apex.net)
* @copyright 2000 Chad Miller (cmiller@surfsouth.com)
*/
+#include "lib/util/strerror.h"
RCSID("$Id$")
#include <freeradius-devel/server/base.h>
el = main_loop_event_list();
}
+ /*
+ * Fix spurious messages
+ */
+ fr_strerror_clear();
sc = fr_schedule_create(NULL, el, &default_log, fr_debug_lvl,
thread_instantiate, thread_detach, schedule);
if (!sc) {
fr_channel_requestor_uctx_add(w->channel, w);
fr_channel_set_recv_reply(w->channel, nr, fr_network_recv_reply);
+ /*
+ * FIXME: This creates a race in the network loop
+ * exit condition, because it can theoretically
+ * be signalled to exit before the workers have
+ * ACKd channel creation.
+ */
nr->num_workers++;
/*
*/
void fr_network(fr_network_t *nr)
{
- while (likely((nr->num_workers > 0) || !nr->exiting)) {
+ /*
+ * Run until we're told to exit AND the number of
+ * workers has dropped to zero.
+ *
+ * This is important as if we exit too early we
+ * free the channels out from underneath the
+ * workers and they read uninitialised memory.
+ *
+ * Whenever a worker ACKs our close notification
+ * nr->num_workers is decremented, so when
+ * nr->num_workers == 0, all workers have ACKd
+ * our close and are no longer using the channel.
+ */
+ while (likely(!(nr->exiting && (nr->num_workers == 0)))) {
bool wait_for_event;
int num_events;
if (!cs) cs = cf_section_find(sc->cs, "worker", NULL);
if (sc->worker_thread_instantiate(sw->ctx, sw->el, cs) < 0) {
- PERROR("%s - Failed calling thread instantiate", worker_name);
+ PERROR("%s - Worker thread instantiation failed", worker_name);
goto fail;
}
}
if (!subcs) subcs = cf_section_find(sc->cs, "worker", NULL);
if (sc->worker_thread_instantiate(sc->single_worker, el, subcs) < 0) {
- PERROR("Failed calling thread instantiate");
+ PERROR("Worker thread instantiation failed");
destroy_both:
fr_network_destroy(sc->single_network);
fr_worker_destroy(sc->single_worker);
ms = fr_channel_responder_uctx_get(ch);
+ fr_assert_msg(fr_dlist_num_elements(&worker->channel[i].dlist) == 0,
+ "Network added messages to channel after sending FR_CHANNEL_CLOSE");
+
fr_channel_responder_ack_close(ch);
fr_assert(ms != NULL);
fr_message_set_gc(ms);
for (i = 0; i < worker->config.max_channels; i++) {
if (!worker->channel[i].ch) continue;
+ worker_requests_cancel(&worker->channel[i]);
+
+ fr_assert_msg(fr_dlist_num_elements(&worker->channel[i].dlist) == 0,
+ "Pending messages in channel after cancelling request");
+
fr_channel_responder_ack_close(worker->channel[i].ch);
}
#include <freeradius-devel/server/module_rlm.h>
#include <freeradius-devel/server/radmin.h>
#include <freeradius-devel/server/request_data.h>
+#include <freeradius-devel/util/strerror.h>
#include <freeradius-devel/unlang/xlat_func.h>
/** Heap of all lists/modules used to get a common index with module_thread_inst_list
}
}
+ /*
+ * So we don't get spurious errors
+ */
+ fr_strerror_clear();
+
DEBUG4("Worker alloced %s thread instance data (%p/%p)", ti->mi->module->name, ti, ti->data);
if (mi->module->thread_instantiate &&
mi->module->thread_instantiate(MODULE_THREAD_INST_CTX(mi->dl_inst, ti->data, el)) < 0) {