Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^2: Malfunctioning select() call on a FIFO

by Llew_Llaw_Gyffes (Scribe)
on Jan 06, 2010 at 18:55 UTC ( [id://815966]=note: print w/replies, xml ) Need Help??


in reply to Re: Malfunctioning select() call on a FIFO
in thread Malfunctioning select() call on a FIFO

The correction on the usage of sysread() is taken. However, I have to point out that this misses the point of the problem. My problem is not how to correctly read from the FIFO; a simple "$fifodata = <FIFO>;" has always worked here (though I'll admit sysread() is probably better). The problem is how to make the select() on the FIFO work properly again instead of always returning true, so that the handler sleeps until there's data available on the FIFO instead of going into a tight loop and repeatedly trying to read from the FIFO as fast as the CPU can execute the inner loop. The only reason I even tried using sysread() instead was in case <FIFO> was somehow leaving something on the FIFO that was making select() think new data had become available to read.

I point out again that this select() call used to work, and has not been changed since then; it's just ... stopped working. The "if (select(...)) {...}" call, on the FIFO, has become effectively an "if (1) {...}" after the first time the other end of the FIFO is written to.

Just to make sure the other end was being properly closed, I wrote this little test tool:

#!/usr/bin/perl my $fifo = shift(@ARGV) || die "No FIFO"; if (-p $fifo) { open(FIFO, ">$fifo") || die "Cannot open $fifo for writing"; print FIFO "/.\n" || die "Cannot write to $fifo"; close(FIFO) || die "Could not close $fifo"; } else { print "$p is not a FIFO.\n"; }

I start the client, it runs normally with negligible CPU utilization; I run the test script; it opens the FIFO, writes to it, closes the FIFO, and exits; the client executes the command sent through the FIFO; and client CPU utilization goes immediately to 100% and stays there, because every select() call on the FIFO after the first command is read from it is saying that there is data on the FIFO to read, even after the writeable end of the FIFO has been closed.

Thinking about it, it's been long enough since I last used this functionality of the client that it's entirely possible that it stopped working when I upgraded from Perl-5.8 to Perl-5.10, or possibly even when I upgraded from Perl-5.6 to Perl-5.8.

Replies are listed 'Best First'.
Re^3: Malfunctioning select() call on a FIFO
by ikegami (Patriarch) on Jan 06, 2010 at 19:30 UTC

    a simple "$fifodata = <FIFO>;" has always worked here (though I'll admit sysread() is probably better).

    Is is better simply because using buffered IO with select is wrong.

    The only reason I even tried using sysread() instead was in case <FIFO> was somehow leaving something on the FIFO

    Leaving stuff on the FIFO is fine. <FIFO> is bad because it can return less than what it reads from the FIFO. That causes select to block when it shouldn't. For example,

    use IO::Select qw( ); use IO::Handle qw( ); pipe(my $rfh, my $wfh) or die; $wfh->autoflush(1); if (fork()) { my $sel = IO::Select->new($rfh); while ($sel->can_read()) { my $got = <$rfh>; last if !defined($got); chomp $got; print("It took ", (time()-$got), " seconds to get the msg\n"); } } else { for (;;) { print($wfh time(), "\n") or die; print($wfh time(), "\n") or die; sleep(3); } }
    It took 0 seconds to get the msg It took 3 seconds to get the msg It took 0 seconds to get the msg It took 3 seconds to get the msg It took 0 seconds to get the msg ...

    But with sysread:

    my $sel = IO::Select->new($rfh); my $buf = ''; while ($sel->can_read()) { sysread($rfh, $buf, 64*1024, length($buf)) or last; while ($buf =~ s/^(.*)\n//) { my $got = $1; print("It took ", (time()-$got), " seconds to get the msg\ +n"); } }
    It took 0 seconds to get the msg It took 0 seconds to get the msg It took 0 seconds to get the msg It took 0 seconds to get the msg It took 0 seconds to get the msg It took 0 seconds to get the msg ...

    I point out again that this select() call used to work, and has not been changed since then;

    And select is still working properly. The problem has nothing to do with select.

    because every select() call on the FIFO after the first command is read from it is saying that there is data on the FIFO to read

    No, it's saying that the handle needs to be serviced. Specifically, it needs to be closed because it reached EOF. I explained this. Stop using select on a handle you're told is closed.

      No, it's saying that the handle needs to be serviced. Specifically, it needs to be closed because it reached EOF. I explained this. Stop using select on a handle you're told is closed.

      Aaaah.... your meaning was not clear to me.  So what you're telling me is that a FIFO, now, must be regarded as a one-shot that can be read to EOF once, then must be closed and re-opened in order to re-use it?  One can no longer simply keep the read end open and wait for more input to be written to it by the same or a different "client"?  (Doing so used to work.  Is it then possibly a now-fixed bug in Perl's handling of FIFOs that it ever did work?)

      I've now rewritten the code to read the FIFO (yes, using sysread), then immediately close and re-open it.  I was concerned that this might introduce the possibility of race conditions, but testing shows that this is not in fact a problem.  Thanks for the explanation of what was happening here; I just didn't actually "get" the key part of the explanation the first time around.

        So what you're telling me is that a FIFO, now, must be regarded as a one-shot that can be read to EOF once

        I didn't say anything about named fifos specifically, so no. But it does seem to be the case. I don't know if there's anything special you can do with named fifos to reset them.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://815966]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2024-04-19 20:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found