summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/indmanager/ind_manager.c27
-rw-r--r--src/indmanager/ind_manager.h2
2 files changed, 26 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;
}
diff --git a/src/indmanager/ind_manager.h b/src/indmanager/ind_manager.h
index 733cf7a..a684ac6 100644
--- a/src/indmanager/ind_manager.h
+++ b/src/indmanager/ind_manager.h
@@ -136,6 +136,7 @@ struct _IMManager {
IMIndType type;
bool running;
bool polling;
+ bool cancelled;
const CMPIBroker *broker;
const CMPIContext *ctx_main; /* main thread */
CMPIContext *ctx_manage; /* manage thread */
@@ -163,6 +164,7 @@ typedef enum {
IM_ERR_THREAD, // some error on threading
IM_ERR_CMPI_RC, // CMPI status not OK
IM_ERR_OP, // bad or null object path
+ IM_ERR_CANCELLED, // job has been cancelled
} IMError;
// Create manager with given properties and callbacks.