How to use O_ASYNC and fcntl in perl?

I want to use the O_ASYNC option and when the pipe can read, the SIGIO handler will work.

but the following code does not work. can anyone 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 5.16.1, operating system Redhat 5u4, kernel 2.6.18, x86_64

+4
source share
2 answers

On Linux, you must request asynchronous notification (O_ASYNC) and specify the recipient (F_SETOWN). So you only need to add one line to your example for it to 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"; 

Run above:

 $ perl so-12640993.pl catch SIGIO! complete 
+4
source

SIGIO based on asynchronous I / O triggers edge scrambling, not the trigger level.

Before any file descriptor sends you SIGIO , you must first arm it. To do this, you need to perform all operations - sysread() in this case - until you get undef / EAGAIN . At this point, the file descriptor will now be enabled for SIGIO and will send a signal when it is ready to read. Then you can read it until it gives EAGAIN , which will EAGAIN it up again.

+1
source

Source: https://habr.com/ru/post/1436816/


All Articles