
# HG changeset patch # User Dan Smith <danms@us.ibm.com> # Date 1215036495 25200 # Node ID eeb54ba6f7b6d3b74b67faefa5e35a12ed5945e9 # Parent b7f53024c5a4d815691aa3112f5effb25df66d20 Fix race between EnableIndications and ActivateFilter's thread Accomplish this by decoupling the enabled-ness of the whole provider from the presence of activated filters against the provider. Keep a count of the number of subscribed filters against us (per platform) and keep the thread running until that reaches zero. Use the enabled-ness of the provider to gate actual delivery of any indications (as intended). The original race was because ActivateFilter could be run before EnableIndications (which seems broken to me -- thanks Pegasus) and thus the thread was started before the global flag was set true. Thus, the thread fell right through the while loop and stopped running. Signed-off-by: Dan Smith <danms@us.ibm.com> diff -r b7f53024c5a4 -r eeb54ba6f7b6 src/Virt_ComputerSystemIndication.c --- a/src/Virt_ComputerSystemIndication.c Wed Jul 02 15:07:48 2008 -0700 +++ b/src/Virt_ComputerSystemIndication.c Wed Jul 02 15:08:15 2008 -0700 @@ -53,6 +53,7 @@ }; static CMPI_THREAD_TYPE thread_id[CSI_NUM_PLATFORMS]; +static int active_filters[CSI_NUM_PLATFORMS]; enum CS_EVENTS {CS_CREATED, CS_DELETED, @@ -331,6 +332,11 @@ char *type_name = NULL; CMPIInstance *affected_inst; + if (!lifecycle_enabled) { + CU_DEBUG("CSI not enabled, skipping indication delivery"); + return false; + } + affected_inst = get_typed_instance(_BROKER, prefix, "ComputerSystem", @@ -413,7 +419,7 @@ free(tmp_list); CU_DEBUG("Entering CSI event loop (%s)", prefix); - while (lifecycle_enabled) { + while (active_filters[platform] > 0) { int i; bool res; bool failure = false; @@ -468,6 +474,8 @@ } out: + CU_DEBUG("Exiting CSI event loop (%s)", prefix); + thread_id[platform] = 0; pthread_mutex_unlock(&lifecycle_mutex); @@ -485,11 +493,14 @@ const CMPIObjectPath* op, CMPIBoolean first) { - CU_DEBUG("ActivateFilter"); CMPIStatus s = {CMPI_RC_OK, NULL}; struct std_indication_ctx *_ctx; struct ind_args *args; int platform; + + CU_DEBUG("ActivateFilter for %s", CLASSNAME(op)); + + pthread_mutex_lock(&lifecycle_mutex); _ctx = (struct std_indication_ctx *)mi->hdl; @@ -533,12 +544,17 @@ args->classname = strdup(CLASSNAME(op)); args->_ctx = _ctx; + active_filters[platform] += 1; + thread_id[platform] = _BROKER->xft->newThread(lifecycle_thread, args, 0); - } + } else + active_filters[platform] += 1; out: + pthread_mutex_unlock(&lifecycle_mutex); + return s; } @@ -549,7 +565,26 @@ const CMPIObjectPath* op, CMPIBoolean last) { - return (CMPIStatus){CMPI_RC_OK, NULL}; + int platform; + CMPIStatus s = {CMPI_RC_OK, NULL}; + + CU_DEBUG("DeActivateFilter for %s", CLASSNAME(op)); + + platform = platform_from_class(CLASSNAME(op)); + if (platform < 0) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unknown platform"); + goto out; + } + + pthread_mutex_lock(&lifecycle_mutex); + active_filters[platform] -= 1; + pthread_mutex_unlock(&lifecycle_mutex); + + pthread_cond_signal(&lifecycle_cond); + out: + return s; } static _EI_RTYPE EnableIndications(CMPIIndicationMI* mi, @@ -566,6 +601,7 @@ static _EI_RTYPE DisableIndications(CMPIIndicationMI* mi, const CMPIContext *ctx) { + CU_DEBUG("DisableIndications"); pthread_mutex_lock(&lifecycle_mutex); lifecycle_enabled = false; pthread_mutex_unlock(&lifecycle_mutex);