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 "$!";
Run above:
$ perl so-12640993.pl catch SIGIO! complete
source share