Reputation: 8874
i want to use O_ASYNC option and when the pipe can read , the SIGIO's handler will run .
but the following code are not work . any one can help me ?
#!/bin/env perl
use Fcntl;
$SIG{IO}= sub {
print "catch SIGIO!\n";
};
my $flags=0;
open(FH,"-|","sleep 4 ;echo aaa") or die "$!";
fcntl(FH,F_GETFL,$flags) or die "$!";
fcntl(FH,F_SETFL,$flags | O_NONBLOCK | O_ASYNC) or die "$!";
sleep(5);
print "complete\n";
my perl version is 5.16.1 , operation system is Redhat 5u4 ,kernel 2.6.18, x86_64
Upvotes: 4
Views: 1404
Reputation: 58544
Under Linux, you must both request asynchronous notification (O_ASYNC) and specify a recipient (F_SETOWN). So, you need only add one line to your example to make it work:
#!/bin/env perl
use Fcntl;
$SIG{IO}= sub {
print "catch SIGIO!\n";
};
my $flags=0;
open(FH,"-|","sleep 4 ;echo aaa") or die "$!";
fcntl(FH,F_GETFL,$flags) or die "$!";
fcntl(FH,F_SETFL,$flags | O_NONBLOCK | O_ASYNC) or die "$!";
fcntl(FH,F_SETOWN,0 + $$) or die "$!"; # <-- Note that we force $$ to be numeric
sleep(5);
print "complete\n";
Running the above:
$ perl so-12640993.pl
catch SIGIO!
complete
Upvotes: 4
Reputation: 8532
SIGIO
based asynchronous IO is edge-triggered, not level triggered.
Before any filehandle will send you a SIGIO
you must first "arm" it. To do that, you need to perform whatever is the operation - sysread()
in this case - until you get an undef
/EAGAIN
. At that point the filehandle will now be armed for SIGIO
and will send a signal when it is next read-ready. You can then read it until it yields EAGAIN
, which will arm it once more.
Upvotes: 1