Does anyone have experience in how to handle signals in threaded program? Many thanks.

Discussion in 'Perl Misc' started by mike, May 29, 2007.

  1. mike

    mike Guest

    Let's see sample1.pl first. In sample1.pl, there is no signal
    capturing.

    #!/usr/bin/perl
    # sample1.pl
    use threads;

    $thr1 = new threads \&sample_sub, 1;
    $thr2 = new threads \&sample_sub, 2;

    print "pid = $$\n";

    sub sample_sub {
    my $SubNumber = shift @_;
    while (1) {
    print "$SubNumber run once...\n";
    sleep(4);
    }
    }

    $thr1->join;
    $thr2->join;

    sample1.pl exited immediately when it captured SIGUSR1.
    Here is the output:

    pid = 14094
    1 run once...
    2 run once...
    1 run once...
    2 run once...
    User defined signal 1

    It is easy to understand that the process just performed the default
    signal response action and didn't care about the threads.

    Let's see sample2.pl. It has signal capturing defined in the thread.

    #!/usr/bin/perl
    # sample2.pl
    use threads;

    $thr1 = new threads \&sample_sub, 1;
    $thr2 = new threads \&sample_sub, 2;

    print "pid = $$\n";

    sub sample_sub {
    my $SubNumber = shift @_;

    $SIG{USR1}= sub { print "got signal.\n"; };

    while (1) {
    print "$SubNumber run once...\n";
    sleep(4);
    }
    }

    $thr1->join;
    $thr2->join;

    sample2.pl also exited immediately when it captured SIGUSR1, just as
    not defined.
    Here is the output:
    pid = 14275
    1 run once...
    2 run once...
    1 run once...
    2 run once...
    User defined signal 1

    Question 1: Which thread captured the SIGUSR1? or just the process
    captured the SIGUSR1?
    Question 2: Why did the program NOT printing "got signal"? seems the
    subroutine doesn't work.

    In sample3.pl, I defined the signal capture outside of the thread.

    #!/usr/bin/perl
    # sample3.pl
    use threads;

    $SIG{USR1}= sub { print "got signal.\n"; };

    $thr1 = new threads \&sample_sub, 1;
    $thr2 = new threads \&sample_sub, 2;

    print "pid = $$\n";

    sub sample_sub {
    my $SubNumber = shift @_;

    while (1) {
    print "$SubNumber run once...\n";
    sleep(4);
    }
    }

    $thr1->join;
    $thr2->join;

    When I sent SIGUSR1 to the process, no any actions were performed, and
    I finally had to kill the process.

    Question 3: Why did the program not capture the signal? seems the join
    method is suspicious.

    Let's see the last sample4.pl. I replaced the join method with detach,
    and also made some other changes regarding the detach.

    #!/usr/bin/perl
    # sample4.pl
    use threads;

    my $exit;
    $SIG{USR1}= sub { print "got signal.\n"; $exit++;};

    $thr1 = new threads \&sample_sub, 1;
    $thr2 = new threads \&sample_sub, 2;

    print "pid = $$\n";

    sub sample_sub {
    my $SubNumber = shift @_;

    while (1) {
    print "$SubNumber run once...\n";
    sleep(4);
    }
    }

    $thr1->detach;
    $thr2->detach;

    while(!$exit) { sleep 1; }

    When sample4.pl captured SIGUSR1, it acted just as I expected. Here is
    the output:

    pid = 14541
    1 run once...
    2 run once...
    1 run once...
    2 run once...
    got signal.
    A thread exited while 3 threads were running.

    Quetion 4: What is the difference between join and detach when the
    process/threads handle signal?
    Quetion 5: Is it possible that the main process capture the signal and
    then send the signal to all threads? How?
    Quetion 6: I wanna code a program that has multiple threads, each
    thread has its own task. Each thread is capable to capture specific
    signal to perform specific job, for example, clean up and exit while
    captured SIGUSR2. I wonder if any of you guys can write me a sample
    code demonstrating how to capture signal in thread.

    I will really appreciate your help, and many thanks for your patience
    to read this posting.
     
    mike, May 29, 2007
    #1
    1. Advertising

  2. mike

    Guest

    mike <> wrote:

    > Let's see sample2.pl. It has signal capturing defined in the thread.
    >
    > #!/usr/bin/perl
    > # sample2.pl
    > use threads;
    >
    > $thr1 = new threads \&sample_sub, 1;
    > $thr2 = new threads \&sample_sub, 2;
    >
    > print "pid = $$\n";
    >
    > sub sample_sub {
    > my $SubNumber = shift @_;
    >
    > $SIG{USR1}= sub { print "got signal.\n"; };
    >
    > while (1) {
    > print "$SubNumber run once...\n";
    > sleep(4);
    > }
    > }
    >
    > $thr1->join;
    > $thr2->join;
    >
    > sample2.pl also exited immediately when it captured SIGUSR1, just as
    > not defined.
    > Here is the output:
    > pid = 14275
    > 1 run once...
    > 2 run once...
    > 1 run once...
    > 2 run once...
    > User defined signal 1
    >
    > Question 1: Which thread captured the SIGUSR1?


    The "main" thread, i.e. the one that was waiting on the join. Which
    didn't have a sig handler in place.

    > or just the process
    > captured the SIGUSR1?


    I don't understand how threading works under the hood, but in some respects
    you can say that the main thread *is* the process.

    > Question 2: Why did the program NOT printing "got signal"? seems the
    > subroutine doesn't work.


    Because the thread that got the signal did not have a sig handler in place.


    > In sample3.pl, I defined the signal capture outside of the thread.
    >
    > #!/usr/bin/perl
    > # sample3.pl
    > use threads;
    >
    > $SIG{USR1}= sub { print "got signal.\n"; };
    >
    > $thr1 = new threads \&sample_sub, 1;
    > $thr2 = new threads \&sample_sub, 2;
    >
    > print "pid = $$\n";
    >
    > sub sample_sub {
    > my $SubNumber = shift @_;
    >
    > while (1) {
    > print "$SubNumber run once...\n";
    > sleep(4);
    > }
    > }
    >
    > $thr1->join;
    > $thr2->join;
    >
    > When I sent SIGUSR1 to the process, no any actions were performed, and
    > I finally had to kill the process.
    >
    > Question 3: Why did the program not capture the signal?


    It did get the signal, at the "perl" level (the program written in C which
    implements Perl). It just didn't do anything visible with it at the "Perl"
    level (the level at which the typical programmer programs in Perl). If you
    set the environment variable PERL_SIGNALS to "unsafe", you would probably
    get the behavior you expected, unless you got a seg-fault instead.

    > seems the join
    > method is suspicious.


    Under "safe" signals, the sig-handler is deferred until it is "safe" to
    execute it. Apparently, this means until after the "join" completes.
    Since the "join" never completes, the sig-handler is never run.


    >
    > Let's see the last sample4.pl. I replaced the join method with detach,
    > and also made some other changes regarding the detach.
    >
    > #!/usr/bin/perl
    > # sample4.pl
    > use threads;
    >
    > my $exit;
    > $SIG{USR1}= sub { print "got signal.\n"; $exit++;};
    >
    > $thr1 = new threads \&sample_sub, 1;
    > $thr2 = new threads \&sample_sub, 2;
    >
    > print "pid = $$\n";
    >
    > sub sample_sub {
    > my $SubNumber = shift @_;
    >
    > while (1) {
    > print "$SubNumber run once...\n";
    > sleep(4);
    > }
    > }
    >
    > $thr1->detach;
    > $thr2->detach;
    >
    > while(!$exit) { sleep 1; }
    >
    > When sample4.pl captured SIGUSR1, it acted just as I expected. Here is
    > the output:
    >
    > pid = 14541
    > 1 run once...
    > 2 run once...
    > 1 run once...
    > 2 run once...
    > got signal.
    > A thread exited while 3 threads were running.
    >
    > Quetion 4: What is the difference between join and detach when the
    > process/threads handle signal?


    It is not the difference between join and detach, it is the difference
    between join and sleep.


    > Quetion 5: Is it possible that the main process capture the signal and
    > then send the signal to all threads? How?
    > Quetion 6: I wanna code a program that has multiple threads, each
    > thread has its own task. Each thread is capable to capture specific
    > signal to perform specific job, for example, clean up and exit while
    > captured SIGUSR2. I wonder if any of you guys can write me a sample
    > code demonstrating how to capture signal in thread.


    I wouldn't touch that with a ten foot pole. If need be, I'd use separate
    processes, rather than threads.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , May 29, 2007
    #2
    1. Advertising

  3. mike

    mike Guest

    Thanks a lot first for your reply.
    Regarding your words "Because the thread that got the signal did not
    have a sig handler in place.", I defined signal handler in thread in
    sample2.pl, how come the signal was not captured? Maybe there are some
    other ways to define signal handler and capture signal in thread.
     
    mike, May 30, 2007
    #3
    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. Beatrice Rutger
    Replies:
    0
    Views:
    383
    Beatrice Rutger
    Jun 3, 2005
  2. John Hosking
    Replies:
    1
    Views:
    349
    johny blog
    Jul 27, 2008
  3. NeoBettyChen
    Replies:
    0
    Views:
    746
    NeoBettyChen
    Jan 14, 2011
  4. Joao Silva
    Replies:
    0
    Views:
    122
    Joao Silva
    Jun 29, 2009
  5. damezumari
    Replies:
    18
    Views:
    471
    Richard Cornford
    Dec 20, 2006
Loading...

Share This Page