Ticket #1780 (closed bug: fixed)

Opened 4 years ago

Last modified 4 years ago

Using StringHandle for STDERR can cause segfaults

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

Description

Here's a simple test case that demonstrates the problem:

.include 'stdio.pasm'

.sub main
    $P0 = getinterp
    $P1 = new ['StringHandle']
    $P1.'open'('blah', 'rw')
    $P0.'stdhandle'(.PIO_STDERR_FILENO, $P1)
    die "whatever"
.end

What I do is map the standard error filehandle to a StringHandle object. Normally this part of the operation works just fine, and I am able to write error messages and extract them from the StringHandle. The problem comes when we have an unhandled exception. Here's a stack trace showing two iterations of what becomes an infinite loop:

Breakpoint 2, die_from_exception (interp=0x8052040, exception=0x80b4c68) at exceptions.c:96
96	    ASSERT_ARGS(die_from_exception)
(gdb) bt
#0  die_from_exception (interp=0x8052040, exception=0x80b4c68) at exceptions.c:96
#1  0x001af64c in Parrot_ex_throw_from_c (interp=0x8052040, exception=0x80b4c68)
    at exceptions.c:350
#2  0x001afb78 in Parrot_ex_throw_from_c_args (interp=0x8052040, ret_addr_unused=0x0, 
    exitcode=27, format=0x36f230 "Cannot write to a closed filehandle") at exceptions.c:448
#3  0x00317815 in Parrot_StringHandle_nci_puts (interp=0x8052040, _self=0x1d446d)
    at stringhandle.c:373
#4  0x002d9f81 in Parrot_NativePCCMethod_invoke (interp=0x8052040, _self=0x80b2508, next=0x0)
    at nativepccmethod.c:117
#5  0x001c9f4f in Parrot_pcc_invoke_from_sig_object (interp=0x8052040, sub_obj=0x80b2508, 
    call_object=0x80b4c08) at pcc.c:317
#6  0x001ca23a in Parrot_pcc_invoke_method_from_c_args (interp=0x8052040, pmc=0x80b4ba8, 
    method_name=0x8073550, signature=0x36e63a "S->I") at pcc.c:208
#7  0x00233f13 in Parrot_io_putps (interp=0x8052040, pmc=0x80b4ba8, s=0x80c3768) at api.c:624
#8  0x0023488c in Parrot_io_eprintf (interp=0x8052040, s=0x364699 "%S\n") at api.c:719
#9  0x001aeef0 in die_from_exception (interp=0x8052040, exception=0x80b4bf8) at exceptions.c:122
#10 0x001af3d2 in Parrot_ex_throw_from_op (interp=0x8052040, exception=0x80b4bf8, 
    dest=0x80fe1bc) at exceptions.c:236
#11 0x001611d8 in Parrot_die_sc (cur_opcode=0x80fe1b4, interp=0x8052040) at core_ops.c:15796
#12 0x0021bdf2 in runops_slow_core (interp=0x8052040, runcore_unused=0x80f1350, pc=0x80fe1b4)
    at cores.c:647
#13 0x0021b1e8 in runops_int (interp=0x8052040, offset=0) at main.c:224
#14 0x001d17d4 in runops (interp=0x8052040, offs=0) at ops.c:127
#15 0x001c9fae in Parrot_pcc_invoke_from_sig_object (interp=0x8052040, sub_obj=0x80b4558, 
    call_object=0x80b4618) at pcc.c:325
#16 0x001b0e67 in Parrot_ext_call (interp=0x8052040, sub_pmc=0x80b4558, 
    signature=0x36e12e "P->") at extend.c:322
#17 0x001aca7b in Parrot_runcode (interp=0x8052040, argc=1, argv=0xbffff318) at embed.c:811
---Type <return> to continue, or q <return> to quit---
#18 0x003364e3 in imcc_run_pbc (interp=0x8052040, output_file=0x0, argc=1, argv=0xbffff318)
    at main.c:415
#19 0x08048fe8 in main (argc=2, argv=0xbffff314) at main.c:149

die_from_exception attempts to write the message "Cannot write to a closed filehandle" to the closed filehandle, which throws the same exception, which calls die_from_exception, which...

This puts us into a really nasty infinite loop that always ends in segfault.

Possible solutions: 1) If we throw an exception while in die_from_exception, we should just close Parrot and not try to handle the new exception 2) Be better about detecting when we can and cannot write to the StringHandle, and don't try to write to it if we're in a state that will cause a problem 3) Figure out why the StringHandle, which I did open (and did not close) is throwing an exception about not being open for writing the final error message. 4) If we're in a die_from_exception, or similar final situation, always write to STDERR, not a PMC type.

We're probably going to want to do some or all of these things eventually.

Change History

Changed 4 years ago by NotFound

1) implemented in r48885

4) can be done if we save the initial setting of STDERR in some non user overridable place.

3) I think rw is not a valid mode for StringHandle but is just ignored, which is inconsistent with other open methods.

2) We detect when we cannot write, and we throw an exception ;)

Changed 4 years ago by bacek

Hello.

I think this ticket can be closed now. Assign to whiteknight for final desicion.

-- Bacek

Changed 4 years ago by whiteknight

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

I'm going to test this one out soon and see how it works.

Changed 4 years ago by whiteknight

  • status changed from assigned to closed
  • resolution set to fixed

This is indeed fixed now. NotFound++

Note: See TracTickets for help on using tickets.