in reply to Re^2: blocking, non-blocking, and semi-blocking
in thread blocking, non-blocking, and semi-blocking

I can't explain the behavior you're observing, but the code you posted is incorrect. You are separating out the two selects, which means it won't check for socket output until it gets tail output, and once it does, it won't check for tail output until it gets socket output. You need to combine them together, and when select returns you have to figure out whether it's the pipe from tail or the socket that has data available.

As for the problem of your tail dying, I suggest you sprinkle salt on it once a week and be careful how you sit down. No, wait, that's wrong. I meant to say that I suspect the tail would fail even if you ran it from the command line -- either because that file doesn't exist, or because your version of tail doesn't support the command-line arguments you're passing it. If you want to tail -f a file that might not exist yet, use tail -F (for GNU tail, at least). If I'm wrong and the cause of death is more mysterious, try either changing "tail -f -n 0 /tmp/test_file |" to "tail -f -n 0 /tmp/test_file 2>&1 | tee /tmp/unhappy.log |", or to "strace -o /tmp/unhappier.log tail -f -n 0 /tmp/test_file". Examine the generated log file to diagnose the problem.

Once you merge the two selects, you can dispense with the timeout too.

Replies are listed 'Best First'.
Re^4: blocking, non-blocking, and semi-blocking
by genecutl (Beadle) on Sep 01, 2004 at 01:55 UTC
    The code does work, it's running right now. This line:

    fcntl( $tail, F_SETFL(), O_NONBLOCK() );

    sets the file to non-blocking. When the code gets to

    if ( @lines = (<$tail>) ) {

    It skips right by if nothing new has been added to the file. In fact, the fcntl statement might not be needed, because this line reads to the current EOF and then continues. The clearerr statement resets the EOF each time around so that the file can be tailed.

    The select statement:

     ($new_readable) = IO::Select->select( $readable_handles, undef, undef, $TIMEOUT );

    times out when no-one is connecting. I'm setting $TIMEOUT to 0.25 seconds. It will only block for that long, before continuing around the loop back to the file read. I'm using 0.25 as a compromise between availability and CPU usage.