diff options
author | Tomas Bzatek <tbzatek@redhat.com> | 2013-12-20 15:34:04 +0100 |
---|---|---|
committer | Tomas Bzatek <tbzatek@redhat.com> | 2013-12-20 15:34:04 +0100 |
commit | 5a8d8f3619ca041aae1c232479aad1aeea747980 (patch) | |
tree | 37144d5a03926b34a781e29ebe498e6f243820b1 | |
parent | b5a3ce9158cafd820a3461dc017d1720061d87de (diff) | |
download | openlmi-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.
-rw-r--r-- | src/indmanager/ind_manager.c | 61 |
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; |