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

Firstly, a very simple signal handling script:
#!/usr/bin/perl use common::sense; use Glib qw/TRUE FALSE/; $SIG{USR1} = \&on_usr1; my $loop = Glib::MainLoop->new( 'default', FALSE ); $loop->run; sub on_usr1 { my $sig = shift; say "somebody told me $sig"; }
If I call him, it will say:
$ ./t_signal.pl & [1] 2637 $ kill -s USR1 2637 somebody told me USR1 $ kill -s USR1 2637 somebody told me USR1 $

However, if I create and open a named pipe for read, like this:
#!/usr/bin/perl use common::sense; use Glib qw/TRUE FALSE/; my $file_pipe = "pipes/$$".'_pipe'; system('mkfifo',$file_pipe)==0 or die $!; my $p_read; open $p_read,'<',$file_pipe or die $!; $SIG{USR1} = \&on_usr1; my $loop = Glib::MainLoop->new( 'default', FALSE ); $loop->run; sub on_usr1 { my $sig = shift; say "somebody told me $sig"; }
and send USR1 using kill, it just crashes:
$ ./t_signal_1.pl & [1] 2638 $ kill -s USR1 2638 $ [1]+ User defined signal 1 ./t_signal_1.pl $
Why?

Replies are listed 'Best First'.
Re: problems on signal handling, Glib mainloop, and named pipe
by ig (Vicar) on Oct 14, 2010 at 07:47 UTC

    Named Pipes says:

    When you open a fifo, the program will block until there’s something on the other end.

    If you move the open after setting up your signal handlers, then your signal will be caught and reported. The problem is your program stops in the open. The signal is received before your signal handler is set up and the default action of SIGUSR1 is to terminate your program.

    If you have some other process open the fifo for writing, then the open in your perl program will return and your program will carry on. Try running it as is, running another process to open the fifo for write, then send your program a signal.

    But, it would probably be best to set up the signal handlers earlier.

      Should I open the fifo inside the signal handler, or I should emit an event to Glib mainloop, and work on the pipe later?

        I guess that depends on why you are opening the fifo and in particular where in your program you want to use it. I don't know about emitting events to Glib mainloop.

        If you describe what you are trying to achieve, someone might be able to give you more guidance.

Re: problems on signal handling, Glib mainloop, and named pipe
by zentara (Cardinal) on Oct 14, 2010 at 13:50 UTC
    I was toying with this and came up with a solution for your test script. It seems that if you do the open (read-write) '+<' instead of '<' , your second script works as intended. I just happened to see it mentioned in some docs about POSIX rules to make non-blocking pipe opens.
    #!/usr/bin/perl use warnings; use strict; use Glib qw/TRUE FALSE/; my $file_pipe = "$$".'_pipe'; system('mkfifo',$file_pipe)==0 or die $!; my $p_read; open $p_read,'+<',$file_pipe or die $!; # needs '+<' instead of '<' t +o be nonblocking $SIG{USR1} = \&on_usr1; my $loop = Glib::MainLoop->new( 'default', FALSE ); #test non-blocking is working my $count = 1; print "$count\n"; #my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 ); $loop->run; sub on_usr1 { my $sig = shift; print "somebody told me $sig\n"; } sub timer_callback{ $count++; print "$count\n"; return 1; }
    $ ./signal-w-pipe & 1 16594 $ 1 kill -s USR1 16594 somebody told me USR1

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