Catching SIGALRM in a thread

Discussion in 'Perl Misc' started by Samuel, May 20, 2007.

  1. Samuel

    Samuel Guest

    The following code:

    --------------
    #!/usr/bin/perl
    use threads;

    sub run {
    my $result = eval q{
    local $SIG{ALRM} = sub { die "timed-out\n" };
    alarm 2;
    sleep 10;
    alarm 0;
    };
    if ($@) {
    print "Error: $@\n";
    }
    }

    print "Running in main thread...\n";
    run2();
    print "Returned. Running in new thread...\n";
    my $thread = threads->new(\&run2);
    print "Joining...\n";
    $thread->join();
    print "Done.\n";
    --------------

    Produces the following output:

    --------------
    $ perl alrmtst.pl
    Running in main thread...
    Error: timed-out

    Returned. Running in new thread...
    Joining...
    Alarm clock
    $
    --------------

    Can anyone explain why the SIGALRM is caught in the main thread but
    not in the new thread? How do you catch SIGALRM in the second case?

    -Samuel
    Samuel, May 20, 2007
    #1
    1. Advertising

  2. Samuel

    Samuel Guest

    On May 20, 1:08 pm, Samuel <> wrote:
    > Can anyone explain why the SIGALRM is caught in the main thread but
    > not in the new thread?


    I see now that thread uses in-process threads, not the operating
    system's threads, so that explains this behavior to some extent (in
    theory, Perl could still have it's own built in signal handler that
    disambiguates the alarms, but apparently that is not the case).

    > How do you catch SIGALRM in the second case?


    So how to you do timeouts in threads? I am using a third party module
    (Net::Telnet) in a thread that uses SIGALRM for the timeout.
    Net::Telnet does provide a way to disable the timeout entirely, but I
    don't know how to replace it. Any ideas?

    -Samuel
    Samuel, May 21, 2007
    #2
    1. Advertising

  3. Samuel

    Guest

    Samuel <> wrote:
    > On May 20, 1:08 pm, Samuel <> wrote:
    > > Can anyone explain why the SIGALRM is caught in the main thread but
    > > not in the new thread?

    >
    > I see now that thread uses in-process threads, not the operating
    > system's threads, so that explains this behavior to some extent (in
    > theory, Perl could still have it's own built in signal handler that
    > disambiguates the alarms, but apparently that is not the case).
    >
    > > How do you catch SIGALRM in the second case?

    >
    > So how to you do timeouts in threads?


    I don't. I use forking instead of threads, almost always. And when
    I can't, I strongly consider using a different language.

    > I am using a third party module
    > (Net::Telnet) in a thread that uses SIGALRM for the timeout.
    > Net::Telnet does provide a way to disable the timeout entirely, but I
    > don't know how to replace it. Any ideas?


    My Net::Telnet documentation doesn't mention thread safety. I'd take that
    as a caution against using Net::Telnet with threads.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , May 21, 2007
    #3
  4. On May 21, 8:16 am, wrote:
    > Samuel <> wrote:
    > > On May 20, 1:08 pm, Samuel <> wrote:
    > > > Can anyone explain why the SIGALRM is caught in the main thread but
    > > > not in the new thread?

    >
    > > I see now that thread uses in-process threads, not the operating
    > > system's threads, so that explains this behavior to some extent (in
    > > theory, Perl could still have it's own built in signal handler that
    > > disambiguates the alarms, but apparently that is not the case).

    >
    > > > How do you catch SIGALRM in the second case?

    >
    > > So how to you do timeouts in threads?

    >
    > I don't. I use forking instead of threads, almost always. And when
    > I can't, I strongly consider using a different language.
    >


    Mixing threads and signals is like trying to drive in high heels. It
    can make for a bad combination if you don't know what you are doing.

    With that, I thought about giving some more insight into what was
    going on. But the moment I started to think, I had these really
    horrible flashbacks to my Mechanical Engineering days. The horrible
    flashbacks ceased when I heard the following next door

    Girl "F-ck you. I'm tired of this sh-t"
    Guy "B-tch, you never told me sh-t"

    Then I realized the days of playing "corporate monkey" where long
    since behind me. I've found a certain peace and happiness working as
    a $11.00/hr Clerk/back-up Janitor in a warehouse despite the fact that
    I'm starting to get gray hair.


    Chad
    grocery_stocker, May 21, 2007
    #4
  5. Samuel

    Samuel Guest

    On Mon, 21 May 2007 15:16:48 +0000, xhoster wrote:

    > I don't. I use forking instead of threads, almost always. And when I
    > can't, I strongly consider using a different language.


    By now, that's pretty much my conclusion. The fact that sharing nested
    objects between threads is only possible by making every object and all
    of it's attributes thread aware makes things *really* cumbersome. I am
    currently looking into the alternatives.

    > My Net::Telnet documentation doesn't mention thread safety. I'd take
    > that as a caution against using Net::Telnet with threads.


    Yay, another problem! Things could have been going a little bit
    smoother... well, at least I have a working prototype.

    Thank you for your comment!

    -Samuel
    Samuel, May 21, 2007
    #5
  6. Samuel

    zentara Guest

    On Mon, 21 May 2007 20:00:05 +0000 (UTC), Samuel <>
    wrote:

    >On Mon, 21 May 2007 15:16:48 +0000, xhoster wrote:
    >
    >> I don't. I use forking instead of threads, almost always. And when I
    >> can't, I strongly consider using a different language.

    >
    >By now, that's pretty much my conclusion. The fact that sharing nested
    >objects between threads is only possible by making every object and all
    >of it's attributes thread aware makes things *really* cumbersome. I am
    >currently looking into the alternatives.
    >
    >> My Net::Telnet documentation doesn't mention thread safety. I'd take
    >> that as a caution against using Net::Telnet with threads.

    >
    >Yay, another problem! Things could have been going a little bit
    >smoother... well, at least I have a working prototype.
    >
    >Thank you for your comment!
    >
    >-Samuel


    Here is an example I have of an ALARM in a thread. It works for me,
    but it may not be what you are looking for. (Honestly I didn't read
    this question slowly :) )
    My notes indicates threads
    and alarms don't work reliably together, but this seems to do OK.

    #!/usr/bin/perl
    use warnings;
    use strict;
    use threads;
    use threads::shared;

    my $waitTime : shared;
    my $done : shared;
    my $return : shared;
    $waitTime = 5;
    $done = 0;
    $return = '';

    my $cmd = './z1';

    my $thr = threads->new(\&my_exec_thread, $cmd);

    while(1){

    if ( $done == 1 ) {
    print "Thread completed \n";
    print "return= $return\n";
    $thr->join;
    last;
    }elsif ( $done eq 'TIMED OUT' ) {
    print "Thread Timed OUT\n";
    $thr->join;
    last;
    }else{next}

    }

    print "1\n";
    ######################################################
    sub my_exec_thread {
    my $cmd = shift;
    print ("In thread ".$cmd."\n");

    my $maxTime = 5;
    my $child_pid;

    local $SIG{ALRM} = sub { die "timeout" };

    eval {
    alarm($maxTime);
    unless ($child_pid = fork) {
    exec $cmd;
    die "could not exec $cmd: $!";
    }
    wait;
    alarm(0);
    };

    if ($@) {
    print $@,"\n";

    if ($@ =~ /timeout/) {
    local $SIG{'HUP'} = 'IGNORE';
    kill('HUP', $child_pid);
    return;
    }
    }

    print "end of thread code block\n";
    }

    __END__

    ##########################################################
    My $cmd ./z1 is simply:

    #!/usr/bin/perl
    use warnings;
    use strict;

    my $count = 0;
    while(1){
    $count++;
    print "$count\n";
    sleep 1;
    }

    __END__


    zentara

    --
    I'm not really a human, but I play one on earth.
    http://zentara.net/japh.html
    zentara, May 22, 2007
    #6
  7. Samuel

    Guest

    zentara <> wrote:
    > On Mon, 21 May 2007 20:00:05 +0000 (UTC), Samuel <>
    > wrote:
    >
    > >On Mon, 21 May 2007 15:16:48 +0000, xhoster wrote:
    > >
    > >> I don't. I use forking instead of threads, almost always. And when I
    > >> can't, I strongly consider using a different language.

    > >
    > >By now, that's pretty much my conclusion. The fact that sharing nested
    > >objects between threads is only possible by making every object and all
    > >of it's attributes thread aware makes things *really* cumbersome. I am
    > >currently looking into the alternatives.
    > >
    > >> My Net::Telnet documentation doesn't mention thread safety. I'd take
    > >> that as a caution against using Net::Telnet with threads.

    > >
    > >Yay, another problem! Things could have been going a little bit
    > >smoother... well, at least I have a working prototype.
    > >
    > >Thank you for your comment!
    > >
    > >-Samuel

    >
    > Here is an example I have of an ALARM in a thread. It works for me,
    > but it may not be what you are looking for.


    What OS and what version of Perl are you using?
    Your code doesn't work for me. The main program is blown away by
    the alarm, without catching it in the SIG{ALRM} and without
    clobbering the z1 process, which just keeps on running.

    This is perl, v5.8.3 built for x86_64-linux-thread-multi

    Thanks,

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , May 22, 2007
    #7
  8. Samuel

    zentara Guest

    On 22 May 2007 15:44:28 GMT, wrote:

    >zentara <> wrote:


    >>
    >> Here is an example I have of an ALARM in a thread. It works for me,
    >> but it may not be what you are looking for.

    >
    >What OS and what version of Perl are you using?
    >Your code doesn't work for me. The main program is blown away by
    >the alarm, without catching it in the SIG{ALRM} and without
    >clobbering the z1 process, which just keeps on running.
    >
    >This is perl, v5.8.3 built for x86_64-linux-thread-multi
    >
    >Thanks,
    >Xho


    You are right, I'm totally wrong. I'll have to mark that one as
    non-working too.
    I may have first tested in back in the Perl5.6 days, but it dosn't
    work now. :-( Maybe it never worked, but I was too dumb to
    notice. :)
    Sorry for the confusion.

    It seems that setting alarm in the thread will kill the main thread.
    Try this, where I set the alarm callback in main, it works. So you
    should be able to work around it. Of course if you want to have separate
    alarms in multiple threads, you are SOL. The only thing you can do in
    that case, is have secondary timer threads instead of alarm, OR use
    an event loop system in your main thread, that can timeout the thread
    by running it's own timer.
    To be honest, I never even use alarm anymore, I setup my own timers,
    since I generally use Tk, or Gtk2. (POE would work too).
    Gtk2's GLib will setup timers even in non-gui programs, as will POE.
    Tk has to be a GUI.

    #!/usr/bin/perl
    use warnings;
    use strict;
    use threads;
    use threads::shared;

    # ALARM DOSN"T WORK WELL IN THREADS

    my $waitTime : shared;
    my $done : shared;
    my $child_pid : shared;
    $waitTime = 5;
    $done = 0;

    my $cmd = './z1';
    my $thr = threads->new(\&my_exec_thread, $cmd);

    $SIG{ALRM} = sub { warn "thread timeout\n";
    kill 9, "$child_pid\n";
    };

    while(1){

    if ( $done == 1 ) {
    print "Thread completed \n";
    $thr->join;
    last;
    }elsif ( $done eq 'TIMED OUT' ) {
    print "Thread Timed OUT\n";
    $thr->join;
    last;
    }else{next}

    }

    print "1\n";
    ######################################################


    sub my_exec_thread {
    my $cmd = shift;
    print ("In thread ".$cmd."\n");

    ###########################################
    # will kill it all, even main thread with message ALARM CLOCK
    #$SIG{ALRM} = sub { warn "thread timeout\n";
    # kill 9, "$child_pid\n";
    # };
    ############################################

    eval {
    alarm($waitTime);
    unless ($child_pid = fork) {
    exec $cmd;
    die "could not exec $cmd: $!";
    }
    print "pid->$child_pid\n";
    wait;
    alarm(0);
    };

    print "--------- $@\n";
    print "end of thread code block , main lives on\n";
    }
    __END__


    zentara

    --
    I'm not really a human, but I play one on earth.
    http://zentara.net/japh.html
    zentara, May 23, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Is SIGALRM getting masked ???

    , Dec 17, 2007, in forum: C Programming
    Replies:
    1
    Views:
    450
    David Thompson
    Dec 30, 2007
  2. Ron Eggler

    SIGALRM in a class member?

    Ron Eggler, Aug 13, 2008, in forum: C++
    Replies:
    8
    Views:
    751
    James Kanze
    Aug 14, 2008
  3. Paul Rubin

    SIGALRM problem

    Paul Rubin, Oct 13, 2008, in forum: Python
    Replies:
    2
    Views:
    443
    Paul Rubin
    Oct 13, 2008
  4. Eric Schwartz

    timeouts with threads and SIGALRM

    Eric Schwartz, Aug 13, 2004, in forum: Ruby
    Replies:
    11
    Views:
    352
    Eric Schwartz
    Aug 20, 2004
  5. Guillaume Marcais

    SIGALRM available?

    Guillaume Marcais, Feb 14, 2005, in forum: Ruby
    Replies:
    2
    Views:
    157
    Guillaume Marcais
    Feb 15, 2005
Loading...

Share This Page