Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Signals vs. Windows

by BrowserUk (Patriarch)
on Oct 03, 2012 at 21:18 UTC ( [id://997135]=note: print w/replies, xml ) Need Help??


in reply to Signals vs. Windows

  1. Signals and Windows:

    Not OS supported. Very limited emulation by Perl. Not reliable.

  2. Signals and threads:

    Signals are, at best, on platforms that support them natively, a very crude form of IPC.

    They are not a useful mechanism of Inter-Thread Communications.

    From the Linux man pages:

    The signal disposition is a per-process attribute: in a multithreaded application, the disposition of a particular signal is the same for all threads.

    A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged.

    A signal may be generated (and thus pending) for a process as a whole (e.g., when sent using kill(2)) or for a specific thread (e.g., certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill(3)). A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.

  3. Signals and blocking-IO:

    Since 5.8, Perl only delivers signals after the currently executing opcode completes (SAFE_SIGNALS). If the currently executing opcode is a blocking IO operation that may never complete -- eg. reading a line from a pipe -- the signal may never be delivered

  4. Sending every known signal:

    Utter desperation. :)

For a solution to your problem that works, see Re^3: trying to get timeout to work (easier with threads).


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.

RIP Neil Armstrong

Replies are listed 'Best First'.
Re^2: Signals vs. Windows
by DanEllison (Scribe) on Oct 04, 2012 at 13:26 UTC
    Signals are, at best, on platforms that support them natively, a very crude form of IPC.

    Yes, everyone is quick to suggest that, and yet not offer any working alternatives. Shared memory is not always an option. Port and pipe communication is excessive.

    If my entire process is being terminated from the keyboard, by a scheduler, or the O/S, a signal is exactly what I'm going to get, and I want to cleanup properly which it does. I was just trying to use the same logic internally to force the cleanup based on a timer.

    Sending every known signal: Utter desperation. :)

    Sending no, capturing yes. I wasn't sending every signal but one, maybe two. Understanding how the app responds to many different situations is just good testing.

    For a solution to your problem that works, see Re^3: trying to get timeout to work (easier with threads).

    Note that your example still uses the devilish signal. But yes, this seems to be the most promising suggestion yet. Resolves the blocking I/O by pushing it another thread deeper. Thank you.

      Note that your example still uses the devilish signal.

      Yes, but in the way it was intended -- as an IPC mechanism, not ITC.

      Resolves the blocking I/O by pushing it another thread deeper. Thank you.

      Indeed. (Be sure to look at the stack_size parameter to threads.)

      But, it isn't actually necessary to go one thread deeper. If your current main/parent thread can attempt to send a signal to its child threads to terminate them, it could also send that signal directly to the processes those child threads are waiting on, thus cutting out the middle man and the need for an extra thread.

      All that would be required is to shared the pids of those processes with the parent thread so that it knows where to send the signal when the time is right.

      The following script starts 5 asynchronous, piped subprocesses in threads that will each run for 5 seconds producing one 'line' of output per second. The threads share the pids of those processes with the main thread via a shared array indexed by their thread ids.

      The main thread then applies timeouts to those processes ranging from 3 to 7 seconds, killing them after the appropriate delay. It then gathers whatever output they had produced before the timeout from the threads by joining them.

      You can see -- in the console output after the __END__ -- that the first two processes were terminated (SIGINT) after 3 and 4 seconds respectively and their output was truncated. The other 3 complete their output and terminate normally.

      #! perl -slw use strict; use Time::HiRes qw[ sleep time ]; use threads; use threads::shared; my @pids :shared; sub asyncPipedProc { my $tid = threads->tid; my $cmd = shift; $pids[ $tid ] = open my $pipe, '-|', $cmd or die $!; my @input; push @input, $_ while <$pipe>; return @input; } my $cmd = q[ perl -E"$|++; sleep(1), say for 1 .. 5" ]; my @running; for my $timeout ( 3 .. 7 ) { push @running, [ threads->new( \&asyncPipedProc, $cmd, $_ ), time() + $timeout ]; } while( @running and sleep 0.1 ) { for my $i ( reverse 0 .. $#running ) { if( $running[ $i ][ 1 ] < time() ) { kill 2, $pids[ $running[ $i ][ 0 ]->tid ]; printf "From thread %d got:\n%s", $running[ $i ][ 0 ]->tid, join'', $running[ $i ][ 0 ]->join; splice @running, $i, 1; } } } __END__ C:\test>multi-timeout.pl Terminating on signal SIGINT(2) From thread 1 got: 1 2 3 Terminating on signal SIGINT(2) From thread 2 got: 1 2 3 4 From thread 3 got: 1 2 3 4 5 From thread 4 got: 1 2 3 4 5 From thread 5 got: 1 2 3 4 5

      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.

      RIP Neil Armstrong

        Yes, I thought about that. But the child thread is doing more than just executing the command. It is also logging the output, start, stop, status.... I'd like the child thread to ultimately send the signal to external program so that it can also record the fact in my log.

        But that's all okay because now the child thread is running asychonously and I can move the timer from the parent down to the child. So in essence, the parent no longer needs to signal the child, and logically you are right that we don't need to be another level deep, but that I am really moving down a level in my hierarchy of threads.

Log In?
Username:
Password:

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

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

    No recent polls found