Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

Win32: Redirect STDOUT to socket

by repellent (Priest)
on Feb 09, 2009 at 06:51 UTC ( #742363=perlquestion: print w/replies, xml ) Need Help??
repellent has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I'm having trouble redirecting STDOUT to a socket. I'm using ActiveState Perl v5.10.0 built for MSWin32-x86-multi-thread.

When $bug_on = 0; this is the output:
got_it> line1 got_it> line2 got_it> line3 123 456

When $bug_on = 1; I expect to see:
got_it> 123 got_it> 456

but it just stalls (on the readline?). I've seen howto redirect STDOUT to $socket but can't seem to figure out what's wrong. I'm stuck. Thanks in advance!

UPDATE #1: Thanks to all who have replied. I updated the code to add in 2 lines of code, adding the suggestion from ikegami.

Now when $bug_on = 1; I get:
999 got_it> 777 got_it> 888 123 456

At this point, after what BrowserUk mentioned, I'm merely curious as to what Perl is really doing internally.

From observation, I think that the STDOUT redirection is not persistent into the exec, and that exec resets STDOUT to the usual because it doesn't know any better. Is this assumption correct?

If so, then how does Perl process backticks to return the STDOUT of a process? All I really want is to manually capture STDOUT of another process without qx() (for my education :). No Tim Toady for backticks in Win32?

UPDATE #2: Big thanks to BrowserUk! So I dived a little deeper and I think I'm drowning badly in Win32 waters... I tried using Win32::Process::Create to spawn a process that will inherit parent filehandles, but the output is still the same as before:
999 got_it> 777 got_it> 888 123 456

I don't think the filehandles are inherited. Any ideas, anyone?

use strict; use warnings; use Socket; # UPDATE #2: added 2 lines below use Win32::Process; use Win32; my $bug_on = 1; sub _pipe_from_fork ($) { my $pid; # emulate pipe() my $WRITE; socketpair($_[0], $WRITE, AF_UNIX, SOCK_STREAM, PF_UNSPEC) and shutdown($_[0], 1) and shutdown($WRITE, 0) or return undef; if (defined($pid = fork())) { unless ($pid) { if ($bug_on) { # UPDATE #1: added 1 line below close(STDOUT); # XXX: BUG open(STDOUT, ">&", $WRITE) or die; } else { print $WRITE "$_\n" for qw(line1 line2 line3); } } } return $pid; } my $pid = _pipe_from_fork(my $READ); die unless defined($pid); if ($pid) { print "got_it> $_" while <$READ>; } else { # UPDATE #1: added 1 line below print `perl -le "print 777; print 888; print STDERR 999"`; # UPDATE #2: commented exec line and added Win32::Process::Create( +) #exec qw(perl -le), 'print 123; print 456' or die; Win32::Process::Create( my $obj, 'C:\\Perl\\bin\\perl.exe', 'C:\\Perl\\bin\\perl.exe -le "print 123; print 456"', # does not inherit filehandles? 1, NORMAL_PRIORITY_CLASS, "." ); }

Replies are listed 'Best First'.
Re: Win32: Redirect STDOUT to socket
by BrowserUk (Pope) on Feb 09, 2009 at 10:01 UTC
      Thanks, BrowserUk. Yes, I know the path of forking on Win32 is fraught with doom :)

      Just curious at this point: how does Perl do qx() in Win32? We can't emulate it another way? Please see my OP update.
Re: Win32: Redirect STDOUT to socket
by juster (Friar) on Feb 09, 2009 at 07:54 UTC

    What you have is a buffering problem. You have to turn autoflushing on for the new STDOUT file handle you make:

    use IO::Handle; # up top ... open STDOUT, '>&', $WRITE or die "failed redirect to STDOUT: $!"; STDOUT->autoflush(1); ...

    Or you can use the perlvar $|, aka $OUTPUT_AUTOFLUSH

    use English qw(-no_match_vars); ... open STDOUT, '>&', $WRITE or die "failed redirect to STDOUT: $!"; $OUTPUT_AUTOFLUSH = 1; ...

    I almost mentioned the select builtin but it gave different output, interestingly!

      Doesn't work for me. After trying your suggestions, it still stalls. I have tried placing after open:
      use IO::Handle; STDOUT->autoflush(1);

      and even
      select((select(STDOUT), $| = 1)[0]);

      to no avail.
Re: Win32: Redirect STDOUT to socket
by ikegami (Pope) on Feb 09, 2009 at 09:56 UTC

    close(STDOUT); before the open makes it work (but I don't know why).

      Thanks, ikegami! It works for within the current "process" only. Please see my update.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://742363]
Front-paged by Arunbear
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2018-05-22 22:44 GMT
Find Nodes?
    Voting Booth?