Using `pthread_cancel` can leave the DB driver in an inconsistent state and may lead to undefined behaviour when cleaning up the plug-in. Instead of cancelling the thread, set a flag and signal the condition variable, thereby giving the thread a chance to exit in good order. Signed-off-by: Jeremy Sowden <jeremy@xxxxxxxxxx> --- include/ulogd/db.h | 1 + util/db.c | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/ulogd/db.h b/include/ulogd/db.h index bf4a19dea150..17eaa7cf60db 100644 --- a/include/ulogd/db.h +++ b/include/ulogd/db.h @@ -47,6 +47,7 @@ struct db_stmt_ring { pthread_mutex_t mutex; int full; + volatile sig_atomic_t shut_down; }; diff --git a/util/db.c b/util/db.c index 6cfbcbc16791..42b59cc6284c 100644 --- a/util/db.c +++ b/util/db.c @@ -184,17 +184,11 @@ ulogd_db_signal(struct ulogd_pluginstance *upi, int signal) case SIGTERM: case SIGINT: if (di->ring.size) { - int s = pthread_cancel(di->ring.thread_id); - if (s != 0) { + di->ring.shut_down = 1; + pthread_cond_signal(&di->ring.cond); + if (pthread_join(di->ring.thread_id, NULL) != 0) ulogd_log(ULOGD_ERROR, - "Can't cancel ring-processing thread\n"); - break; - } - s = pthread_join(di->ring.thread_id, NULL); - if (s != 0) { - ulogd_log(ULOGD_ERROR, - "Error waiting for ring-processing thread cancellation\n"); - } + "Error waiting for ring-processing thread exit\n"); } break; default: @@ -371,8 +365,6 @@ _stop_db(struct ulogd_pluginstance *upi) di->stmt = NULL; } if (di->ring.size > 0) { - pthread_cancel(di->ring.thread_id); - pthread_cond_destroy(&di->ring.cond); pthread_mutex_destroy(&di->ring.mutex); @@ -832,11 +824,11 @@ _process_ring(void *arg) pthread_mutex_lock(&di->ring.mutex); - while(1) { + while(!di->ring.shut_down) { pthread_cond_wait(&di->ring.cond, &di->ring.mutex); - while (di->ring.used > 0) { + while (!di->ring.shut_down && di->ring.used > 0) { memcpy(stmt, _get_ring_elem(&di->ring, di->ring.rd_idx), di->ring.length); @@ -859,9 +851,13 @@ exec_stmt: * statement. */ di->driver->close_db(upi); - while (di->driver->open_db(upi) < 0) - sleep(1); - goto exec_stmt; + while (!di->ring.shut_down) { + if (di->driver->open_db(upi) < 0) { + sleep(1); + continue; + } + goto exec_stmt; + } } -- 2.35.1