Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

What is wrong in blocking?

by madtoperl (Pilgrim)
on May 11, 2006 at 11:58 UTC ( #548678=perlquestion: print w/replies, xml ) Need Help??
madtoperl has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks
For some time when i turn blocking off for a file handle that points to *STDERR,
it also turns blocking off for *STDIN. I am using perl 5.8.1 . Here is the code:
my $fhandle = IO::Handle->new(); if (!$fhandle->fdopen(*STDERR, "a")) { die("Error: Unable to open \"err\" file handle: $!\n"); } $fhandle->autoflush(1); $fhandle->blocking(0); In a: while ( <STDIN> ) { doIt($_); }
As soon as we turn blocking off for STDERR, STDIN no longer blocks.
I tried to turn blocking on for STDIN with STDIN->blocking(1),
but then STDERR now has blocking turned on.

Expecting your help

Replies are listed 'Best First'.
Re: What is wrong in blocking?
by blazar (Canon) on May 11, 2006 at 12:57 UTC
    if (!$fhandle->fdopen(*STDERR, "a"))

    I'm not really sure if it can be used like that... the documentation says:

    $io->fdopen ( FD, MODE ) "fdopen" is like an ordinary "open" except that its first p +arameter is not a filename but rather a file han- dle name, an IO::Handle object, or a file descriptor number +.

    I don't know if a typeglob is acceptable there. OTOH if it were not one would expect the call to fail... isn't it that *STDERR is being considered numeric and equal to 0 there?

    $ perl -le 'print 0+*STDERR' 0

    Mind you, I'm just wild-guessing... in doubt try with fileno STDERR (==2 if you haven't changed it!)

Re: What is wrong in blocking?
by sgifford (Prior) on May 11, 2006 at 13:10 UTC
    How very strange. For me, the problem only seems to happen when STDIN and STDERR are left at their defaults. For example, these work:
    perl t50 </dev/tty perl t50 2>/dev/null
    The problem may stem from this attribute of dup(2):
    dup and dup2 create a copy of the file descriptor oldfd.

    After successful return of dup or dup2, the old and new descriptors may be used interchangeably. They share locks, file position pointers and flags; for example, if the file position is modified by using lseek on one of the descriptors, the position is also changed for the other.

    I suspect this dup happens in your login program, such as ssh or /bin/login.

    Note that this behavior isn't perl-specific; I see the exact same thing with this C program:

    #include <unistd.h> #include <stdio.h> #include <fcntl.h> void main() { char buf[8192]; int rr; fcntl(STDERR_FILENO,F_SETFL,O_NONBLOCK); while ( (rr = read(STDIN_FILENO,buf,8192)) > 0) { write(STDOUT_FILENO,buf,rr); } if (rr < 0) { perror("read error:"); exit(1); } exit(0); }

    Whether or not this is a bug depends on POSIX, I suppose.

    At any rate, hopefully one of the above workarounds will help. Good luck!

    Update: It looks like this is How Things Have Always Worked. If you look at init.c from V7 Unix, the dfork function takes the tty on standard input and dup's it twice to create standard output and standard error. session.c from OpenSSH does essentially the same thing in its do_exec_pty function.

Re: What is wrong in blocking?
by chromatic (Archbishop) on May 11, 2006 at 18:50 UTC

    I don't understand the assumptions behind this question.

    How did you open STDERR for writing, so that it blocks?

    How did you get STDERR in a state where it buffers writes?

Re: What is wrong in blocking?
by jesuashok (Curate) on May 11, 2006 at 12:01 UTC

    Both the main process and the backgrounded one (the "child" process) share the same STDIN, STDOUT and STDERR filehandles. If both try to access them at once, strange things can happen. You may want to close or reopen these for the child.
    You can get around this with opening a pipe (see open) but on some systems this means that the child process cannot outlive the parent. That might be the reason for it.

    "Keep pouring your ideas"

      Which "backgrounded child process"?!?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://548678]
Approved by jesuashok
[choroba]: The problem was bigger, as the test tried to call a method that didn't exist anymore
[marinersk]: :: ducking ::
[choroba]: because, someone renamed the method, but didn't notice it was used in the test, as the test was skipped
[marinersk]: Well, if the method doesn't exist, it would be hard to pass the test.
[choroba]: later, someone removed the new method, as all its usage places were safe, but didn't notice the test still used the old name
[choroba]: fortunately, it wasn't that hard to replace the method and fix a few remaining failures due to the changes we did to the codebase over the years
[marinersk]: choroba Sounds like a process improvement opportunity; tests may not all need to be run, but they should all be compiled with perl -c before check-in/promotion happens.
[choroba]: so, now I have the test, so I can start making changes in the code. Back to the original ticket, yay!
[marinersk]: I definitely love it when my $current_taask=& taskPop(); if ($current_task eq $original_task) { } is true.
[marinersk]: s/taask/task/g;

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (14)
As of 2017-05-25 15:14 GMT
Find Nodes?
    Voting Booth?