Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

non-blocking IO from open("-|")ing an external program with fcntl

by bliako (Monsignor)
on Jun 12, 2020 at 13:23 UTC ( [id://11117980]=perlquestion: print w/replies, xml ) Need Help??

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

I was looking for a way to read the output of an external command piping its output to a script in a non-blocking way. I read that using Fcntl's fcntl() can be used to add the O_NONBLOCK flag to the file handle and wonder whether that is a safe practice when that filehandle came from opening an external command and reading its output using: open(my $fh, '-|', 'ls -al'); This is an example:

use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); my $pid = open my $fh, '-|', 'sleep 3; echo aaaa' // die $!; my $flags = fcntl($fh, F_GETFL, 0) or die "failed to get flags, $!"; + fcntl($fh, F_SETFL, $flags | O_NONBLOCK) or die "Couldn't set file fla +gs: $!\n"; my $output = <$fh>; if( defined $output ){ print "got output: '$output'\n" } else { print "no output right now.\n" } print "now waiting to end ...\n"; #waitpid $pid, 0; close($fh); #kill 'TERM', $pid; print "end.\n";

I wanted to turn the above into a CUFP but I am not sure what are the caveats wrt Perl and OS. Anyone knows if any?

bw, bliako

Replies are listed 'Best First'.
Re: non-blocking IO from open("-|")ing an external program with fcntl
by kikuchiyo (Hermit) on Jun 12, 2020 at 13:46 UTC

    IIRC this doesn't work on Windows; in practice, the only useful thing you can use in a non-blocking way on that OS is a network socket. (At least, it doesn't work with straightforward, portable Perl code, you have to use a Win32 API call to achieve something comparable). (Also, this was true a few years ago on Windows 7. I haven't touched their newer products.)

    If you search among my past writeups, you can find a worked GTK2 example that runs a background process and communicates bidirectionally with it.

Re: non-blocking IO from open("-|")ing an external program with fcntl
by jwkrahn (Abbot) on Jun 12, 2020 at 21:38 UTC
    my $pid = open my $fh, '-|', 'sleep 3; echo aaaa' // die $!;

    That will never die because of precedence. (The string 'sleep 3; echo aaaa' is always true.)

    $ perl -MO=Deparse -e'my $pid = open my $fh, "-|", "sleep 3; echo aaaa +" // die $!;' my $pid = open(my $fh, '-|', 'sleep 3; echo aaaa'); -e syntax OK

    You need to add parentheses:

    $ perl -MO=Deparse -e'my $pid = open( my $fh, "-|", "sleep 3; echo aaa +a" ) // die $!;' my $pid = open(my $fh, '-|', 'sleep 3; echo aaaa') // die($!); -e syntax OK

      oops!

Re: non-blocking IO from open("-|")ing an external program with fcntl
by haukex (Archbishop) on Jun 12, 2020 at 22:05 UTC

    I would suggest IPC::Run. Although you often need to ignore test failures when installing the module on Windows, I just tested one of my code examples (this one) on Windows and it seems to work fine.

      thanks, IPC::Run looks good as it takes a callback sub to be called whenever there is output from the spawned command without blocking script flow. Which is clean solution.

Re: non-blocking IO from open("-|")ing an external program with fcntl
by perlfan (Vicar) on Jun 12, 2020 at 17:34 UTC
    Seems like you're over complicating it, use fork directly or Parallel::ForkManager, then use Storable to retreive the data from disk (or ramdisk I suppose). Since you're on Windows, the following may be more relevant (based on my quick bing'ing):

    The benefit to using a fork based approach is you can control the parent program to make it async unti you don't want it to be by using wait.

    Final note, using something like redis if it is available really makes it easy to share data among processes. This is what's it is for. Or maybe sqlite.

      thanks

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11117980]
Approved by marto
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-03-28 14:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found