From 5e39c59eec7618b06fa2c26a77dfafd90a349e44 Mon Sep 17 00:00:00 2001 From: Thierry Bordaz Date: Jul 24 2018 09:45:35 +0000 Subject: Ticket 49848 - Nunc-stans event thread can be hanging shortly when a job is (re)armed Bug Description: When a nunc-stans job is rearmed, event_q_notify enqueue the job and notify the event thread. The first thing event thread does is to lock the job. But until internal_ns_job_rearm release the lock, event thread is hanging. This is also the case of a worker thread (work_q_notify) but has less negative impact Fix Description: Release the lock of the job before calling event_q_notify/work_q_notify https://pagure.io/389-ds-base/issue/49848 Reviewed by: ? Platforms tested: F27 Flag Day: no Doc impact: no --- diff --git a/src/nunc-stans/ns/ns_thrpool.c b/src/nunc-stans/ns/ns_thrpool.c index 774607c..ae2072a 100644 --- a/src/nunc-stans/ns/ns_thrpool.c +++ b/src/nunc-stans/ns/ns_thrpool.c @@ -260,6 +260,15 @@ internal_ns_job_rearm(ns_job_t *job) /* I think we need to check about is_shutdown here? */ + /* + * weither it will wakeup a NS worker thread (work_q) or the NS event thread (event_q) + * This thread will acquire the job->monitor. + * To prevent the thread to wait just release the lock before waking it + * + * This is specifically important for the event thread + */ + pthread_mutex_unlock(&(job->monitor)); + if (NS_JOB_IS_IO(job->job_type) || NS_JOB_IS_TIMER(job->job_type) || NS_JOB_IS_SIGNAL(job->job_type)) { event_q_notify(job); } else { @@ -267,7 +276,6 @@ internal_ns_job_rearm(ns_job_t *job) /* Prevents an un-necessary queue / dequeue to the event_q */ work_q_notify(job); } - pthread_mutex_unlock(&(job->monitor)); } static void @@ -1027,6 +1035,7 @@ ns_add_job(ns_thrpool_t *tp, ns_job_type_t job_type, ns_job_func_t func, void *d if (!_job) { return NS_ALLOCATION_FAILURE; } + pthread_mutex_lock(&(_job->monitor)); /* fill in a pointer to the job for the caller if requested */ if (job) { *job = _job; @@ -1036,6 +1045,7 @@ ns_add_job(ns_thrpool_t *tp, ns_job_type_t job_type, ns_job_func_t func, void *d ns_log(LOG_DEBUG, "ns_add_job %x state %d moving to NS_JOB_ARMED\n", _job, (_job)->state); #endif _job->state = NS_JOB_NEEDS_ARM; + pthread_mutex_unlock(&(_job->monitor)); internal_ns_job_rearm(_job); return NS_SUCCESS; @@ -1218,8 +1228,8 @@ ns_job_rearm(ns_job_t *job) ns_log(LOG_DEBUG, "ns_rearm_job %x state %d moving to NS_JOB_NEEDS_ARM\n", job, job->state); #endif job->state = NS_JOB_NEEDS_ARM; - internal_ns_job_rearm(job); pthread_mutex_unlock(&(job->monitor)); + internal_ns_job_rearm(job); return NS_SUCCESS; } else if (!NS_JOB_IS_PERSIST(job->job_type) && job->state == NS_JOB_RUNNING) { /* For this to be called, and NS_JOB_RUNNING, we *must* be the callback thread! */