Fix a problem with reaping a thread with detached children

When a thread that has detached children is reaped the detached children
need to be fully detached so they can be reaped correctly. If they are not
fully detached then they may reference a parent that has already been
reaped (memory freed). Found with valgrind.
This commit is contained in:
Cary R 2013-11-20 18:01:03 -08:00
parent f47af361cd
commit 04bab6b197
1 changed files with 26 additions and 19 deletions

View File

@ -601,16 +601,28 @@ void vthreads_delete(struct __vpiScope*scope)
/* /*
* Reaping pulls the thread out of the stack of threads. If I have a * Reaping pulls the thread out of the stack of threads. If I have a
* child, then hand it over to my parent. * child, then hand it over to my parent or fully detach it.
*/ */
static void vthread_reap(vthread_t thr) static void vthread_reap(vthread_t thr)
{ {
if (! thr->children.empty()) { if (! thr->children.empty()) {
for (set<vthread_t>::iterator cur = thr->children.begin() for (set<vthread_t>::iterator cur = thr->children.begin()
; cur != thr->children.end() ; ++cur) { ; cur != thr->children.end() ; ++cur) {
vthread_t curp = *cur; vthread_t child = *cur;
assert(curp->parent == thr); assert(child);
curp->parent = thr->parent; assert(child->parent == thr);
child->parent = thr->parent;
}
}
if (! thr->detached_children.empty()) {
for (set<vthread_t>::iterator cur = thr->detached_children.begin()
; cur != thr->detached_children.end() ; ++cur) {
vthread_t child = *cur;
assert(child);
assert(child->parent == thr);
assert(child->i_am_detached);
child->parent = 0;
child->i_am_detached = 0;
} }
} }
if (thr->parent) { if (thr->parent) {
@ -2224,11 +2236,6 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
while (! scope->threads.empty()) { while (! scope->threads.empty()) {
set<vthread_t>::iterator cur = scope->threads.begin(); set<vthread_t>::iterator cur = scope->threads.begin();
/* If I am disabling myself, then remember that fact so
that I can finish this statement differently. */
if (*cur == thr)
disabled_myself_flag = true;
if (do_disable(*cur, thr)) if (do_disable(*cur, thr))
disabled_myself_flag = true; disabled_myself_flag = true;
} }