# HG changeset patch
# User Dan Smith <danms(a)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(a)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);