chromatic wrote:
On Saturday 08 March 2008 07:31:08 Ron Blaschke wrote:

I've been looking into a failure of F<t/dynoplibs/myops.t> on Windows,
but I don't think the problem is limited to that platform.

$ prove t\dynoplibs\myops.t
t\dynoplibs\myops......5/10
t\dynoplibs\myops......6/10 #   Failed test 'three alarm'
#   at t\dynoplibs\myops.t line 118.
# Exited with error code: 255
# Received:
# alarm1
# alarm2
# alarm3
#
# Expected:
# /alarm1
# alarm2
# alarm3/
#

The test output is good, but the error code is 255.  Actually, the test
exits with an access violation.

After stepping through things a couple of times with a debugger I think
the cause for this is that through the final DOD run (Parrot_exit ->
Parrot_really_destroy -> Parrot_do_dod_run) the scheduler is destroyed
*before* the last task.

When the task is finally destroyed, the scheduler is already 0xdeadbeef.
  Here's the final stack trace.

Parrot_cx_delete_task
Parrot_Timer_destroy
Parrot_dod_free_pmc
Parrot_dod_sweep
Parrot_dod_ms_run
Parrot_do_dod_run
Parrot_really_destroy
Parrot_exit

At this line in Parrot_cx_delete_task.

     VTABLE_delete_keyed_int(interp, interp->scheduler, tid);


That's as far as I got.  I don't know enough about the DOD details to
make a good guess on the cause.  Maybe both scheduler and task are
determined to be not-reachable, but the destruction sequence is not
ordered?

The destruction sequence is not ordered, so if a task happens to have a PMC header created prior to the scheduler's PMC header, then this problem will occur. (We reuse PMC headers, so this can happen in not-easily-deterministic ways.)

Making the scheduler a constant PMC would likely fix this, but then anything to which the scheduler points also has to be constant.

It might be possible to finish the scheduled tasks prior to destroying all PMCs.

Not sure if I'm going into the wrong direction here, but can't this happen with any PMC? Say I write my own scheduler and task PMCs, working similarly? Or any other PMCs where destroy calls out to another PMC?

I guess this depends on the contract of destroy. If destroy may not call out to any other PMC, a special case for the scheduler is fine, because it really is special. If destroy may call out there needs to be additional or different handling, to ensure the referenced object is not collected first. In that case, it sounds akin to finalizers in a JVMisch, CLRisch senes. With all the fun border cases, like a PMC resurrecting, for example by registering itself at a live PMC. At least this last issue seems to be covered by PDD 17 by "...make sure that you don't leave any references to it in any Parrot structure by the end of the method." In this sense, C<interp->scheduler> in Timer counts as a reference, and doesn't follow the rule. Or does it? I'm confused.

Thanks,
Ron

Reply via email to