Permalink
Browse files

[GC] Made the concurrency scheduler a constant PMC. This means that i…

…t never

gets collected by the end-of-the-world GC run before all tasks and timers and
events (which depend on it for their destruction) get collected and destroyed.
See RT #60622 for one example of that.

Of course, as it's a constant PMC now, it always needs its live flag cleared
just before it gets marked as live, otherwise it won't have a chance to perform
its custom marking of the PObjs to which it refers.  This is a workaround, but
the real fix is to figure out safe and consistent order of destruction, and
that's a much larger patch.

I also tidied some related code.

git-svn-id: https://svn.parrot.org/parrot/trunk@32841 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 42c97cd commit b703022dba30d8893a64ea7149eeea78bea010cd @chromatic chromatic committed Nov 19, 2008
Showing with 18 additions and 13 deletions.
  1. +9 −3 src/gc/dod.c
  2. +5 −8 src/inter_create.c
  3. +2 −1 src/pmc/parrotinterpreter.pmc
  4. +2 −1 src/scheduler.c
View
@@ -298,8 +298,14 @@ Parrot_dod_trace_root(PARROT_INTERP, int trace_stack)
pobject_lives(interp, (PObj *)interp->root_namespace);
/* mark the concurrency scheduler */
- if (interp->scheduler)
+ if (interp->scheduler) {
+ /* the scheduler is a constant PMC, but it's an aggregate
+ * clearing the live flag here forces it to mark its children
+ * but it won't get collected during global destruction before tasks do
+ * See RT #60622 for the symptom of that problem */
+ PObj_live_CLEAR((PObj *)interp->scheduler);
pobject_lives(interp, (PObj *)interp->scheduler);
+ }
/* s. packfile.c */
mark_const_subs(interp);
@@ -323,8 +329,8 @@ Parrot_dod_trace_root(PARROT_INTERP, int trace_stack)
Parrot_IOData_mark(interp, interp->piodata);
/* quick check if we can already bail out */
- if (arena_base->lazy_dod && arena_base->num_early_PMCs_seen >=
- arena_base->num_early_DOD_PMCs)
+ if (arena_base->lazy_dod
+ && arena_base->num_early_PMCs_seen >= arena_base->num_early_DOD_PMCs)
return 0;
/* Find important stuff on the system stack */
View
@@ -309,10 +309,7 @@ Note that C<exit_code> is ignored.
void
Parrot_really_destroy(PARROT_INTERP, SHIM(int exit_code), SHIM(void *arg))
{
-
- /*
- * wait for threads to complete if needed; terminate the event loop
- */
+ /* wait for threads to complete if needed; terminate the event loop */
if (!interp->parent_interpreter) {
Parrot_cx_runloop_end(interp);
pt_join_threads(interp);
@@ -327,7 +324,7 @@ Parrot_really_destroy(PARROT_INTERP, SHIM(int exit_code), SHIM(void *arg))
* Need to turn off DOD blocking, else things stay alive and IO
* handles aren't closed
*/
- interp->arena_base->DOD_block_level =
+ interp->arena_base->DOD_block_level =
interp->arena_base->GC_block_level = 0;
if (Interp_trace_TEST(interp, ~0)) {
@@ -344,9 +341,9 @@ Parrot_really_destroy(PARROT_INTERP, SHIM(int exit_code), SHIM(void *arg))
Parrot_do_dod_run(interp, GC_finish_FLAG);
#if STM_PROFILE
- if (interp->thread_data && interp->thread_data->stm_log &&
- !interp->parent_interpreter &&
- Interp_debug_TEST(interp, PARROT_THREAD_DEBUG_FLAG))
+ if (interp->thread_data && interp->thread_data->stm_log
+ && !interp->parent_interpreter
+ && Interp_debug_TEST(interp, PARROT_THREAD_DEBUG_FLAG))
Parrot_STM_dump_profile(interp);
#endif
@@ -47,7 +47,8 @@ clone_interpreter(Parrot_Interp d, Parrot_Interp s, INTVAL flags)
/* we block DOD runs while cloning since C<d> is not yet running */
Parrot_block_GC_mark(d);
- d->scheduler = pmc_new(d, enum_class_Scheduler);
+ /* create as constant to avoid order-of-destruction errors, RT #60622 */
+ d->scheduler = constant_pmc_new(d, enum_class_Scheduler);
d->scheduler = VTABLE_share_ro(d, d->scheduler);
if (flags & PARROT_CLONE_RUNOPS)
View
@@ -72,7 +72,8 @@ Parrot_cx_init_scheduler(PARROT_INTERP)
/* Add the very first interpreter to the list of interps. */
pt_add_to_interpreters(interp, NULL);
- scheduler = pmc_new(interp, enum_class_Scheduler);
+ /* create as constant to avoid order-of-destruction errors, RT #60622 */
+ scheduler = constant_pmc_new(interp, enum_class_Scheduler);
scheduler = VTABLE_share_ro(interp, scheduler);
interp->scheduler = scheduler;

0 comments on commit b703022

Please sign in to comment.