Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Correct code crashes ActivePerl Interpreter

by heiermann (Novice)
on Jan 17, 2011 at 20:59 UTC ( [id://882751]=perlquestion: print w/replies, xml ) Need Help??

heiermann has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I am back again with another "funny" behaviour of ActivePerl. I am using v5.12.2 on Windows 2008 SP1.

I want to read from a long-running co-process, and I want to be able to interrupt that procedure. In the meantime I want to calculate something asyncronously in a thread, but this thread should not be interruptible to join it in the end.

This code crashes my Perl interpreter:

#! /usr/bin/perl -w use strict; use threads; # Starting a co-process to read from. my $procid = open(READ, '-|', 'perl -e "$|=1; $SIG{INT} = \'IGNORE\'; +for ($i=0;$i<10;$i++) {print \"Line $i\n\"; sleep 1;}"'); my $break = 0; $SIG{INT} = sub { $break=1; }; sub calculation { local $SIG{INT} = 'IGNORE'; print("calculating somet +hing\n"); 5; } my $thread = async(\&calculation); # Reading from co-process. until ($break) { my $line = <READ>; last unless defined $line; print $line; } if ($break) { kill('ABRT', $procid); } close(READ); print $thread->join() ."\n";

Earlier you gave me the advice, not to use signals on Windows heavily, because they cannot be expected to work in all situations.

However, I think it is unbelievable that correct code can crash the interpreter. And, btw, the code is working properly whithout the thread. Can anybody explain?

----------

Thanks for your helping answers. I think BrowserUk gave the correct hint.

Replies are listed 'Best First'.
Re: Correct code crashes ActivePerl Interpreter (perlbug)
by BrowserUk (Patriarch) on Jan 17, 2011 at 22:26 UTC

    This is nothing to do with signals or signal handling; and it is a bug.

    It appears to stem from the piped-open filehandle being cloned into the thread causing a conflict when the thread is joined.

    A simple workaround is to start the thread before you do the piped open:

    #! /usr/bin/perl -w use strict; use threads; my $break = 0; $SIG{INT} = sub { $break=1; }; sub calculation { local $SIG{INT} = 'IGNORE'; print("calculating something\n"); 5; } my $thread = async(\&calculation); # Starting a co-process to read from. my $procid = open( READ, '-|', 'perl -e "$|=1; $SIG{INT} = \'IGNORE\'; for ($i=0;$i<10;$i++) {pri +nt \"Line $i\n\"; sleep 1;}"' ); # Reading from co-process. until ($break) { my $line = <READ>; last unless defined $line; print $line; } if ($break) { kill('ABRT', $procid); } close(READ); print $thread->join() ."\n";

    You should raise a perlbug against this. The following minimised code demonstrates the problem (5.10.1):

    #! /usr/bin/perl -w use strict; use threads; sub calculation { print("calculating something\n"); 5; } # Starting a co-process to read from. my $procid = open( READ, '-|', 'perl -e "$|=1; for (1..10) {print \"Line $_\n\"; sleep 1;}"' ); ##switch the order of the previous and next lines and the crash does n +ot occur. my $thread = async(\&calculation); # Reading from co-process. until ( 0 ) { my $line = <READ>; last unless defined $line; print $line; } close(READ); print $thread->join() ."\n";

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Correct code crashes ActivePerl Interpreter
by BrowserUk (Patriarch) on Jan 17, 2011 at 23:12 UTC

    You can also fix the problem by using a lexical file handle.

Re: Correct code crashes ActivePerl Interpreter
by ww (Archbishop) on Jan 17, 2011 at 22:09 UTC
Re: Correct code crashes ActivePerl Interpreter
by ikegami (Patriarch) on Jan 17, 2011 at 21:27 UTC

    [ Not related to the crash. ]

    Your SIGINT handling seems a bit fishy. Do realise that signals are per process, not per thread? You tell the system the process should do something in response to SIGINT, but then you almost immediately go and tell the system the process should ignore SIGINT (until caluations are done).

    This may be correct, but I think having one handler for SIGINT would be cleaner, and just change the behaviour of the handler based on the current state. For starters, your model would fail if you ran two instances of your calculation thread in parallel.

Re: Correct code crashes ActivePerl Interpreter
by Anonyrnous Monk (Hermit) on Jan 17, 2011 at 21:26 UTC

    Are you sure about the 'ABRT' signal — it's a rather unusual signal to send, as - at least on Unix (not sure about its Windows emulation) - it would abnormally terminate the process, with the default action leading to a core dump (unless disabled), just like SIGSEGV, SIGILL or SIGFPE.

    Also, how exactly does it "crash"? Immediately upon start, when you interrupt it, etc... (maybe you're just seeing the result of you yourself aborting the subprocess?)

Re: Correct code crashes ActivePerl Interpreter
by ikegami (Patriarch) on Jan 17, 2011 at 21:32 UTC

    The distinction between crashing and being forcibly exited is minute if it exists. Are you sure this crash isn't the child being forcibly terminated at your request? (Upd: I mean the kill request, if it's not clear. )

Re: Correct code crashes ActivePerl Interpreter
by afoken (Chancellor) on Jan 17, 2011 at 22:32 UTC

    Windows has no signals. Perl offers a minimal signal emulation that has its own problems. See also Re: Handling killing the perl process and Re: Signals in Strawberry Perl: Name or number?.

    Windows also has no fork() and no exec() API. Recent perl versions offer a more or less fragile emulation based on interpreter threads. In other words: Perl fakes several forked processes of the same script in a single Windows process.

    Using both emulations plus threads is just begging for trouble.

    Don't use signals, don't use fork(), don't use exec() on Windows. If you want signals, fork(), and exec(), get rid of Windows and run a UNIX derivate (*BSD, Linux, ...) instead. If you can't get rid of Windows, use Windows API functions instead of the fragile emulations. See Win32, Win32::API, Win32::Process and others.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      That may all be true for some definition of the term, but it is also completely irrelevant to the OPs problem.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://882751]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2024-04-23 23:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found