summaryrefslogtreecommitdiffstats
path: root/src/indmanager
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2013-12-20 15:34:04 +0100
committerTomas Bzatek <tbzatek@redhat.com>2013-12-20 15:34:04 +0100
commit5a8d8f3619ca041aae1c232479aad1aeea747980 (patch)
tree37144d5a03926b34a781e29ebe498e6f243820b1 /src/indmanager
parentb5a3ce9158cafd820a3461dc017d1720061d87de (diff)
downloadopenlmi-providers-5a8d8f3619ca041aae1c232479aad1aeea747980.tar.gz
openlmi-providers-5a8d8f3619ca041aae1c232479aad1aeea747980.tar.xz
openlmi-providers-5a8d8f3619ca041aae1c232479aad1aeea747980.zip
indmanager: Properly detach the manage thread from CIMOM
Accomplished that by registering a pthread cleanup handler that gets called on thread cancellation as well as on normal exit. A minor code shuffle had to be done since the cleanup handlers are macros in fact and no control flow commands (return, continue) should be called within.
Diffstat (limited to 'src/indmanager')
-rw-r--r--src/indmanager/ind_manager.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/src/indmanager/ind_manager.c b/src/indmanager/ind_manager.c
index d6cd650..fcd232f 100644
--- a/src/indmanager/ind_manager.c
+++ b/src/indmanager/ind_manager.c
@@ -657,30 +657,19 @@ bool send_indication(CMPIInstance *old, CMPIInstance *new, IMManager *manager)
/*
* Run in separate thread
*/
-static void *manage(void *data)
+static IMError manage(IMManager *manager)
{
- // TODO: Switch Enable/Disable state on some places?
- IMManager *manager = (IMManager *)data;
IMError err = IM_ERR_OK; // TODO - How to handle potential errors?
- DEBUG("manage thread started");
-
IMPolledDiffs diffs = {NULL};
CMPIInstance *iold = NULL, *inew = NULL;
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
-
- DEBUG("manage thread - attaching thread manager context = %p", manager->ctx_manage);
- CBAttachThread(manager->broker, manager->ctx_manage);
-
while (1) {
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;
+ return IM_ERR_CANCELLED;
}
while (!manager->running) {
DEBUG("manage thread waiting to indication start");
@@ -690,7 +679,7 @@ static void *manage(void *data)
if (manager->polling) {
if (!first_poll(manager, &err)) {
pthread_mutex_unlock(&manager->_t_mutex);
- return (void *)err;
+ return err;
}
}
pthread_mutex_unlock(&manager->_t_mutex);
@@ -702,19 +691,18 @@ static void *manage(void *data)
pthread_mutex_lock(&manager->_t_mutex);
if (manager->cancelled) {
pthread_mutex_unlock(&manager->_t_mutex);
- err = IM_ERR_CANCELLED;
- return (void *)err;
+ return IM_ERR_CANCELLED;
}
if (manager->polling) {
// poll enumerations
if (!_im_poll(manager, &err)) {
pthread_mutex_unlock(&manager->_t_mutex);
- return (void *)err;
+ return err;
}
// create list of diffs
if (!gen_diffs(manager, &diffs, &err)) {
pthread_mutex_unlock(&manager->_t_mutex);
- return (void *)err;
+ return err;
}
manager->data = &diffs;
}
@@ -726,6 +714,40 @@ static void *manage(void *data)
}
}
+static void manage_cleanup(void *data)
+{
+ IMManager *manager = (IMManager *)data;
+
+ DEBUG("manage thread - detaching thread manager context = %p", manager->ctx_manage);
+ CBDetachThread(manager->broker, manager->ctx_manage);
+}
+
+/* Wrapper thread function, to isolate code control flow due to sensitive pthread_cleanup_ macros */
+static void *manage_wrapper(void *data)
+{
+ // TODO: Switch Enable/Disable state on some places?
+ IMManager *manager = (IMManager *)data;
+ IMError err;
+
+ DEBUG("manage thread started");
+
+ /* Allow thread cancellation */
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+
+ DEBUG("manage thread - attaching thread manager context = %p", manager->ctx_manage);
+ CBAttachThread(manager->broker, manager->ctx_manage);
+
+ /* Main execution block closed in a cleanup handler */
+ pthread_cleanup_push(manage_cleanup, data);
+ err = manage(manager);
+ pthread_cleanup_pop(1);
+
+ DEBUG("manage thread stopped");
+
+ return (void *)err;
+}
+
/*
* Default gather function using polling
* It is going thru all polled instances. If there is some pair (previous enum
@@ -1191,7 +1213,7 @@ bool im_start_ind(IMManager *manager, const CMPIContext *ctx, IMError *err)
manager->ctx_manage = CBPrepareAttachThread(manager->broker,
manager->ctx_main);
DEBUG("Creating second thread");
- if (pthread_create(&manager->_t_manage, NULL, manage, manager)) {
+ if (pthread_create(&manager->_t_manage, NULL, manage_wrapper, manager)) {
*err = IM_ERR_THREAD;
return false;
}
@@ -1244,7 +1266,6 @@ bool im_stop_ind(IMManager *manager, const CMPIContext *ctx, IMError *err)
/* Cleanup */
remove_all_enums(manager, 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;