Previously, if process.C ran its destructors before generator.C, then
Counter::locks would be destroyed before int_cleanup. The latter is
responsible for ending the handler thread, which may still be trying to
adjust locks. Boost's mutex throws an exception if you try to acquire a
destroyed lock, which kills the whole process uncleanly.
Now the locks are created as a new[] pointer, and are simply leaked when
the process ends, no real harm done.
---
proccontrol/src/int_process.h | 2 +-
proccontrol/src/process.C | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/proccontrol/src/int_process.h b/proccontrol/src/int_process.h
index e89f4402c50c..f7679f2eeadd 100644
--- a/proccontrol/src/int_process.h
+++ b/proccontrol/src/int_process.h
@@ -184,7 +184,7 @@ class Counter {
void adjust(int val);
- static Mutex<> locks[NumCounterTypes];
+ static Mutex<> * locks;
static int global_counts[NumCounterTypes];
};
diff --git a/proccontrol/src/process.C b/proccontrol/src/process.C
index 72b10deefa67..53a421f3f1da 100644
--- a/proccontrol/src/process.C
+++ b/proccontrol/src/process.C
@@ -8063,7 +8063,13 @@ bool Breakpoint::suppressCallbacks() const
return llbreakpoint_->suppressCallbacks();
}
-Mutex<false> Counter::locks[Counter::NumCounterTypes];
+// Note: These locks are intentionally indirect and leaked!
+// This is because we can't guarantee destructor order between compilation
+// units, and a static array of locks here in process.C may be destroyed before
+// int_cleanup in generator.C. Thus the handler thread may still be running,
+// manipulating Counters, which throws an exception when it tries to acquire
+// the destroyed lock.
+Mutex<false> * Counter::locks = new Mutex<false>[Counter::NumCounterTypes];
int Counter::global_counts[Counter::NumCounterTypes];
Counter::Counter(CounterType ct_) :
--
1.9.0
|