diff options
Diffstat (limited to 'src/indmanager/ind_manager.c')
-rw-r--r-- | src/indmanager/ind_manager.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/src/indmanager/ind_manager.c b/src/indmanager/ind_manager.c index 462227e..d6cd650 100644 --- a/src/indmanager/ind_manager.c +++ b/src/indmanager/ind_manager.c @@ -677,6 +677,11 @@ static void *manage(void *data) DEBUG("manage thread in infinite loop"); // wait until manager is running pthread_mutex_lock(&manager->_t_mutex); + if (manager->cancelled) { + pthread_mutex_unlock(&manager->_t_mutex); + err = IM_ERR_CANCELLED; + return (void *)err; + } while (!manager->running) { DEBUG("manage thread waiting to indication start"); pthread_cond_wait(&manager->_t_cond, &manager->_t_mutex); @@ -695,6 +700,11 @@ static void *manage(void *data) continue; } pthread_mutex_lock(&manager->_t_mutex); + if (manager->cancelled) { + pthread_mutex_unlock(&manager->_t_mutex); + err = IM_ERR_CANCELLED; + return (void *)err; + } if (manager->polling) { // poll enumerations if (!_im_poll(manager, &err)) { @@ -819,6 +829,7 @@ IMManager* im_create_manager(IMInstGather gather, IMFilterChecker f_checker, manager->filters = NULL; manager->running = false; manager->polling = polling; + manager->cancelled = false; manager->broker = broker; manager->f_checker = f_checker; manager->enums = NULL; @@ -1175,6 +1186,7 @@ bool im_start_ind(IMManager *manager, const CMPIContext *ctx, IMError *err) *err = IM_ERR_THREAD; return false; } + manager->cancelled = false; manager->ctx_main = ctx; manager->ctx_manage = CBPrepareAttachThread(manager->broker, manager->ctx_main); @@ -1205,17 +1217,25 @@ bool im_stop_ind(IMManager *manager, const CMPIContext *ctx, IMError *err) DEBUG("Stopping indications"); manager->running = false; - /* We must lock the mutex so we are sure the thread does not hold it. - * If we destroy the thread with mutex locked, the mutex is locked forever. - */ + /* First lock the mutex so we are sure the thread does not hold it. */ pthread_mutex_lock(&manager->_t_mutex); + /* Then cancel the thread in deferred mode and set a private flag. + * The thread may be doing unlocked stuff that will cancel just fine + * or may be waiting for mutex acquisition where it will cancel and + * unlock right after that using our private flag. + */ + manager->cancelled = true; + /* Note that mutex functions ARE NOT cancellation points! */ if (pthread_cancel(manager->_t_manage)) { *err = IM_ERR_THREAD; pthread_mutex_unlock(&manager->_t_mutex); return false; } + + /* Unlock the mutex and give the thread chance to cancel properly. */ pthread_mutex_unlock(&manager->_t_mutex); + /* Wait until thread cancellation is finished. */ if (pthread_join(manager->_t_manage, NULL)) { *err = IM_ERR_THREAD; return false; @@ -1226,6 +1246,7 @@ bool im_stop_ind(IMManager *manager, const CMPIContext *ctx, IMError *err) manager->data = NULL; /* TODO: properly detach the thread using CBAttachThread(), needs to be called from the thread */ manager->ctx_manage = NULL; + manager->cancelled = false; return true; } |