Commit 4d22fb5f authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'fix_event_deadlock' into 'master'

Fix event deadlock

See merge request !969
parents 1c27f80b 0782d247
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -70,7 +70,7 @@ static int evsched_run(dthread_t *thread)
/* Run event loop. */
pthread_mutex_lock(&sched->heap_lock);
while (!dt_is_cancelled(thread)) {
if (!!EMPTY_HEAP(&sched->heap)) {
if (!!EMPTY_HEAP(&sched->heap) || sched->paused) {
pthread_cond_wait(&sched->notify, &sched->heap_lock);
continue;
}
......@@ -250,3 +250,18 @@ void evsched_join(evsched_t *sched)
{
dt_join(sched->thread);
}
void evsched_pause(evsched_t *sched)
{
pthread_mutex_lock(&sched->heap_lock);
sched->paused = true;
pthread_mutex_unlock(&sched->heap_lock);
}
void evsched_resume(evsched_t *sched)
{
pthread_mutex_lock(&sched->heap_lock);
sched->paused = false;
pthread_cond_signal(&sched->notify);
pthread_mutex_unlock(&sched->heap_lock);
}
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -61,7 +61,7 @@ typedef struct event {
* \brief Event scheduler structure.
*/
typedef struct evsched {
volatile bool running; /*!< True if running. */
volatile bool paused; /*!< Temporarily stop processing events. */
pthread_mutex_t heap_lock; /*!< Event heap locking. */
pthread_cond_t notify; /*!< Event heap notification. */
struct heap heap; /*!< Event heap. */
......@@ -137,6 +137,17 @@ int evsched_schedule(event_t *ev, uint32_t dt);
*/
int evsched_cancel(event_t *ev);
/*! \brief Start event processing threads. */
void evsched_start(evsched_t *sched);
/*! \brief Stop event processing threads. */
void evsched_stop(evsched_t *sched);
/*! \brief Join event processing threads. */
void evsched_join(evsched_t *sched);
/*! \brief Temporarily stop processing events. */
void evsched_pause(evsched_t *sched);
/*! \brief Resume processing events. */
void evsched_resume(evsched_t *sched);
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -237,8 +237,7 @@ static int zone_status(zone_t *zone, ctl_args_t *args)
if (MATCH_OR_FILTER(args, CTL_FILTER_STATUS_EVENTS)) {
for (zone_event_type_t i = 0; i < ZONE_EVENT_COUNT; i++) {
// Events not worth showing or used elsewhere.
if (i == ZONE_EVENT_LOAD || i == ZONE_EVENT_UFREEZE ||
i == ZONE_EVENT_UTHAW) {
if (i == ZONE_EVENT_UFREEZE || i == ZONE_EVENT_UTHAW) {
continue;
}
......@@ -1406,9 +1405,12 @@ static int server_status(ctl_args_t *args)
if (strcasecmp(type, "version") == 0) {
ret = snprintf(buff, sizeof(buff), "Version: %s", PACKAGE_VERSION);
} else if (strcasecmp(type, "workers") == 0) {
int running_bkg_wrk, wrk_queue;
worker_pool_status(args->server->workers, &running_bkg_wrk, &wrk_queue);
ret = snprintf(buff, sizeof(buff), "UDP workers: %zu, TCP workers %zu, "
"background workers: %zu", conf_udp_threads(conf()),
conf_tcp_threads(conf()), conf_bg_threads(conf()));
"background workers: %zu (running: %d, pending: %d)",
conf_udp_threads(conf()), conf_tcp_threads(conf()),
conf_bg_threads(conf()), running_bkg_wrk, wrk_queue);
} else if (strcasecmp(type, "configure") == 0) {
ret = snprintf(buff, sizeof(buff), "%s", CONFIGURE_SUMMARY);
} else {
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -881,9 +881,8 @@ void server_update_zones(conf_t *conf, server_t *server)
knot_zonedb_foreach(server->zone_db, zone_events_freeze);
}
/* Suspend workers, clear wating events, finish running events. */
worker_pool_suspend(server->workers);
worker_pool_clear(server->workers);
/* Suspend adding events to worker pool queue, wait for queued events. */
evsched_pause(&server->sched);
worker_pool_wait(server->workers);
/* Reload zone database and free old zones. */
......@@ -893,8 +892,8 @@ void server_update_zones(conf_t *conf, server_t *server)
/* Trim extra heap. */
mem_trim();
/* Resume workers and allow events on new zones. */
worker_pool_resume(server->workers);
/* Resume processing events on new zones. */
evsched_resume(&server->sched);
if (server->zone_db) {
knot_zonedb_foreach(server->zone_db, zone_events_start);
}
......
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -227,3 +227,16 @@ void worker_pool_clear(worker_pool_t *pool)
worker_queue_init(&pool->tasks);
pthread_mutex_unlock(&pool->lock);
}
void worker_pool_status(worker_pool_t *pool, int *running, int *queued)
{
if (!pool) {
*running = *queued = 0;
return;
}
pthread_mutex_lock(&pool->lock);
*running = pool->running;
*queued = worker_queue_length(&pool->tasks);
pthread_mutex_unlock(&pool->lock);
}
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -75,3 +75,8 @@ void worker_pool_assign(worker_pool_t *pool, struct task *task);
* \brief Clear all tasks enqueued in pool processing queue.
*/
void worker_pool_clear(worker_pool_t *pool);
/*!
* \brief Obtain info regarding how the pool is busy.
*/
void worker_pool_status(worker_pool_t *pool, int *running, int *queued);
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -60,3 +60,8 @@ task_t *worker_queue_dequeue(worker_queue_t *queue)
return task;
}
size_t worker_queue_length(worker_queue_t *queue)
{
return queue ? list_size(&queue->list) : 0;
}
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -58,3 +58,8 @@ void worker_queue_enqueue(worker_queue_t *queue, task_t *task);
* \return Task or NULL if the queue is empty.
*/
task_t *worker_queue_dequeue(worker_queue_t *queue);
/*!
* \brief Return number of tasks in worker queue.
*/
size_t worker_queue_length(worker_queue_t *queue);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment