http://www.perlmonks.org?node_id=936291

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

I'm trying to ssh to multiple nodes in parallel via threads and it seems to work just fine. Only problem is when a node doesn't support passwordless ssh things go south.

My solution is to simply wait awhile in a loop, and if the ssh fails kill the thread. I read previous notes about setting up a signal handler in the thread and I tried that and it seems to work just fine. The reason I know this is I have a 'print' in the signal handler and I do see the results. Only problem was when the script eventually exits, it reports:

Perl exited with active threads: 0 running and unjoined 1 finished and unjoined
and I'm not sure what to do. What I did do was write a pretty small script that starts the thread, gives it a few seconds to run, and if the ssh doesn't finish and set a flag, it kills the thread. Only thing is now my signal isn't even firing! So now this is turning into a 2-part question:
- why doesn't the signal fire in the thread and
- if it does fire, how do I get rid of the 'unjoined' message at the end?
#!/usr/bin/perl -w use threads; use threads::shared; my $sshDone:shared; $sshDone=0; my $th=threads->create('test'); $th->join(); sleep 3; if (!$sshDone) { $th->kill('KILL'); print "Kill signal sent\n"; } sleep 2; sub test { $SIG{'KILL'} = sub { print "KILL THREAD\n"; threads->exit(); }; `ssh foo\@poker date`; $sshDone=1; }
note - if I use a valid user/hostname the script runs just fine and exits cleanly.

what is happening now is I see the echo of the password prompt to the ssh and then nothing! If I remove the join, I see the 'kill signal sent' message but then it just hangs.

gotta be something simple but I'm just not seeing it.

-mark

Replies are listed 'Best First'.
Re: yet another thread/signal question
by BrowserUk (Patriarch) on Nov 06, 2011 at 14:24 UTC
    1. why doesn't the signal fire in the thread
    2. if it does fire, how do I get rid of the 'unjoined' message at the end?

    The problem fact is that signals are per-process events. So, even though you've set up a signal handler in your thread, the main thread is being interrupted by the signal before your thread ever gets a chance to see it.

    The signal interrupts the th->join call in your main thread and, as you don't have a signal handler there, the process is terminated. As the the thread un-joined at that point, you get the error message.

    The bottom line is that using signals and threads doesn't work.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.
      >The bottom line is that using signals and threads doesn't work.

      sorry to hear that. I guess I was reacting to another posting here in which this very capability was being suggested. I tried to find it to post the topic number but alas couldn't find it. I'm certain you're right because your description certainly described what I'm seeing.

      I just realized if I simply kill the ssh, the thread is able to continue and cleanly exist! Perfect, and much cleaner too. ;)

      -mark

      My experience has been that you can get signals to a thread, but it's totally unpredictable - sometimes the child thread(s) will get the signal and sometimes the main thread gets it. Still, in the end it's not really usable.

        If you set up signal handlers in all the threads, then which one actually gets it will be (in)determined by whichever one of them next gets a time slice after the signal is raised. Ie. In the hands of the gods.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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: yet another thread/signal question
by zentara (Archbishop) on Nov 06, 2011 at 19:51 UTC
    My experience has been that you can get signals to a thread, but it's totally unpredictable - sometimes the child thread(s) will get the signal and sometimes the main thread gets it. Still, in the end it's not really usable.

    The way it works is the main thread gets all signals first, then it sends them on to the child threads... makes sense to me. Then each thread needs to have it's own handler. Each thread can be tracked by it's pid. Here is a simple script to play with. :-)

    #!/usr/bin/perl use warnings; use strict; use threads 'exit' => 'threads_only'; my $thr; print "I'm the parent pid-> $$\n"; my $thr1 = threads->new(\&sub1); my $thr2 = threads->new(\&sub2); my $thr3 = async{ my $myobject = threads->self; my $mytid= $myobject->tid; $SIG{'KILL'} = sub{ print "tid $mytid exiting\n"; threads->exit() } +; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t\t\t\t\t\t$mytid -> $count\n"; sleep 1; } }; for(1..10){ print "$_\n"; if( $_ == 4 ){ $thr1->kill('KILL')->detach } if( $_ == 7 ){ $thr2->kill('KILL')->detach } if( $_ == 9 ){ $thr3->kill('KILL')->detach } sleep 1; } exit; sub sub1{ my $myobject = threads->self; my $mytid= $myobject->tid; $SIG{'KILL'} = sub{ print "tid $mytid exiting\n"; threads->exit() }; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t$mytid -> $count\n"; sleep 1; } } sub sub2{ my $myobject = threads->self; my $mytid= $myobject->tid; $SIG{'KILL'} = sub{ print "tid $mytid exiting\n"; threads->exit() }; print "In the thread $myobject tid->$mytid \n"; my $count = 0; while(1){ $count++; print "\t\t\t\t\t$mytid -> $count\n"; sleep 1; } }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh