Ticket #321 (closed bug: fixed)

Opened 13 years ago

Last modified 12 years ago

Segfault overriding init sub in PIR

Reported by: Infinoid Owned by: whiteknight
Priority: normal Milestone:
Component: none Version:
Severity: fatal Keywords:
Cc: Language:
Patch status: Platform:


Got a bug report in #parrot tonight from ron, who provided the following test script:

.sub main :main
    .local pmc integer_cl, three_cl, three_obj, i

    get_class integer_cl, 'Integer'
    subclass three_cl, integer_cl, 'Three'

    three_obj = new 'Three'
    three_obj = 3

    i = new 'Integer'
    i = 2

    $P0 = sub three_obj, i
    say 'talking about subtraction result:'
    say $P0

.namespace ['Three']

.sub init :method :vtable
    say 'in init'

This results in a segfault. I think he was testing on cygwin with 0.9.0, but I was able to reproduce on linux/x86-64 with trunk r36608:

in init
in init
[New Thread 0x7fc7ff4ac700 (LWP 28160)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fc7ff4ac700 (LWP 28160)]
0x00007fc7fec961b5 in Parrot_init_arg_op (interp=0x1e04080, ctx=0x1f63ee0,
    pc=0x7fff074e89c8, sti=0x7fff074e8848) at src/call/pcc.c:608
608             sig_pmc = ctx->constants[*pc]->u.key;
(gdb) bt
#0  0x00007fc7fec961b5 in Parrot_init_arg_op (interp=0x1e04080, ctx=0x1f63ee0,
    pc=0x7fff074e89c8, sti=0x7fff074e8848) at src/call/pcc.c:608
#1  0x00007fc7fec9b765 in Parrot_init_ret_nci (interp=0x1e04080,
    st=0x7fff074e87f0, sig=0x7fc7fef26434 "P") at src/call/pcc.c:529
#2  0x00007fc7fecb5fb8 in set_nci_P (interp=0x1e04080, st=0x7fff074e87f0,
    val=0x1f00d60) at src/nci.c:147
#3  0x00007fc7fecb9fdf in pcf_P_JPPP (interp=0x1e04080, self=0x1edb6e0)
    at src/nci.c:565
#4  0x00007fc7fedd333a in Parrot_NCI_invoke (interp=0x1e04080, pmc=0x1edb6e0,
    next=0x0) at ./src/pmc/nci.pmc:320
#5  0x00007fc7fec985b9 in Parrot_pcc_invoke_from_sig_object (interp=0x1e04080,
    sub_obj=0x1edb6e0, sig_obj=0x1f00eb0) at src/call/pcc.c:2978
#6  0x00007fc7fecac3b0 in Parrot_mmd_multi_dispatch_from_c_args (
    interp=0x1e04080, name=0x7fc7fef2c616 "subtract",
    sig=0x7fc7fef2c60f "PPP->P") at src/multidispatch.c:337
#7  0x00007fc7fed9a19f in Parrot_default_subtract (interp=0x1e04080,
    pmc=0x1f01630, value=0x1f00ee0, dest=0x1e91a40)
    at ./src/pmc/default.pmc:1281
#8  0x00007fc7fee7c766 in Parrot_Object_subtract (interp=0x1e04080,
    pmc=0x1f01630, value=0x1f00ee0, dest=0x1e91a40) at ./src/pmc/object.c:7482
#9  0x00007fc7fec104c8 in Parrot_sub_p_p_p (cur_opcode=0x1f60388,
    interp=0x1e04080) at src/ops/math.ops:884
#10 0x00007fc7fece8d65 in runops_slow_core (interp=0x1e04080, pc=0x1f60388)
    at src/runops_cores.c:451
#11 0x00007fc7fec9fc45 in runops_int (interp=0x1e04080, offset=0)
    at src/interpreter.c:978
#12 0x00007fc7feca074a in runops (interp=0x1e04080, offs=0)
    at src/call/ops.c:106
#13 0x00007fc7feca0af8 in runops_args (interp=0x1e04080, sub=0x1f03070,
    obj=0x1e91a40, meth_unused=0x0, sig=0x7fc7fef23673 "vP", ap=0x7fff074ecdf0)
    at src/call/ops.c:246
#14 0x00007fc7feca1eac in Parrot_runops_fromc_args (interp=0x1e04080,
    sub=0x1f03070, sig=0x7fc7fef23673 "vP") at src/call/ops.c:313
#15 0x00007fc7fec7b7ee in Parrot_runcode (interp=0x1e04080, argc=1,
    argv=0x7fff074ed0f0) at src/embed.c:984
#16 0x00007fc7feef8374 in imcc_run_pbc (interp=0x1e04080, obj_file=0,
    output_file=0x0, argc=1, argv=0x7fff074ed0f0) at compilers/imcc/main.c:824
#17 0x00007fc7feef9007 in imcc_run (interp=0x1e04080,
    sourcefile=0x7fff074edf99 "ron.pir", argc=1, argv=0x7fff074ed0f0)
    at compilers/imcc/main.c:1111
#18 0x0000000000400c14 in main (argc=1, argv=0x7fff074ed0f0) at src/main.c:61
(gdb) print ctx
$7 = (Parrot_Context *) 0x1f63ee0
(gdb) print ctx->constants
$8 = (struct PackFile_Constant **) 0x1f60420
(gdb) print *pc
$9 = 140733315992448
(gdb) print pc[-1]
$10 = 0
(gdb) print pc[1]
$11 = 140733315992240


mmdvtableprob.t Download (2.6 KB) - added by ronaldws 13 years ago.
tt321_pcc_class.patch Download (1.3 KB) - added by ronaldws 13 years ago.

Change History

in reply to: ↑ description ; follow-up: ↓ 3   Changed 13 years ago by ronaldws

Here is some of my analysis of the problem:

The parrot subtraction operator, sub, uses mmd in the default pmc. If you are using a parrot integer pmc it supplies, among others, a subtract mmd function that takes the difference between two integer pmcs and returns a pmc of the type of the first operand. Somewhere in the preparatory phases of mmd the mmd function invocation sets up a context that expects a result. Like other mmd functions, integer pmc subtract calls vtable methods that can be overridden in a subclass. When the overridden vtable method returns a value, like get_integer it seems to work OK. When the overridden vtable method does NOT return a value like init or set_integer_native it core dumps. AFAICT on the way out of the overridden vtable function, a set_returns operation that notices the mmd function context in caller_ctx->results_signature and then sets it to NULL, seemingly corrupting the context expected by the mmd function.

I will attach an additional test file demonstrating the problem more formally.

Changed 13 years ago by ronaldws

  Changed 13 years ago by whiteknight

  • owner set to whiteknight
  • status changed from new to assigned

in reply to: ↑ 1   Changed 13 years ago by whiteknight

I've been looking at this a little bit too. A backtrace shows that the segfault occurs in src/call/pcc.c:Parrot_init_arg_op where pc is non-null, but *pc = 343597383680 (on my system anyway). This pc value is well out of range for ctx->constants[*pc].

The subtract mmd call resolves to Parrot_Integer_mmd_subtract_Integer_pmc (src/pmc/integer.pmc:501-518). This calls pmc_new to create the result. pmc_new, in a roundabout way, calls the init vtable override. to invoke it, the Class PMC calls src/pmc/class.pmc:initialize_parents (which is a poor name for the function, I think). This uses Parrot_run_meth_from_c_args to call the vtable override, instead of something that's more robust like Parrot_PCCINVOKE or Parrot_pcc_invoke_method_from_c_args. Parrot_run_meth_from_c_args is clobbering the context values, which causes the error.

I've got fix set up that fixes this (and sets a prototype for the eventual s/Parrot_run_meth_fromc_args/Parrot_pcc_invoke_method_from_c_args/ replacement in src/pmc/object.pmc). I'm testing now and will commit if i haven't broken anything.

  Changed 13 years ago by whiteknight

should be fixed in r36915.

  Changed 13 years ago by allison

Unfortunately, this fix breaks t/benchmark/benchmarks.t, particularly the tests of examples/benchmarks/oo*.pasm. Reverted in r37374.

Changed 13 years ago by ronaldws

  Changed 13 years ago by ronaldws

I have come up with a somewhat revised and extended version whiteknight's patch that seems to fix the problem with benchmarks.t without breaking anything. Passes make test, make benchmark_tests, and seems to perform identically on other test groups with parrot that does not have patch.

  Changed 12 years ago by coke

  • status changed from assigned to closed
  • resolution set to fixed
  • severity changed from medium to fatal

As of r41185, this sample code outputs:

in init
in init
talking about subtraction result:

without segfaulting.

Note: See TracTickets for help on using tickets.