Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^3: STDERR going to string

by salva (Monsignor)
on Oct 11, 2011 at 14:20 UTC ( #930827=note: print w/ replies, xml ) Need Help??


in reply to Re^2: STDERR going to string
in thread STDERR going to string

Are you using ActiveState or Strawberry Perl? and which version?

It seems that there is a missmatch between what Perl sees as its file descriptor 2 and the C lib file descriptor 2.

use File::Temp qw(tempfile); use Inline 'C'; open my $olderr, '>&STDERR'; # save STDERR my ($fh, $fn) = tempfile(); open STDERR, '>&', $fh; printf "fileno STDERR: %d\n", fileno(STDERR); print STDERR "foo!"; test_err(); open STDERR, '>&', $olderr; # reset STDERR close $fh; open my $e, '<', $fn; my $err = <$e>; print "|$err|\n"; __END__ __C__ void test_err() { FILE *err = fdopen(2, "a+"); (void)fprintf (err, "ERROR"); } # here it says: # fileno STDERR: 2 # |foo!| # ERROR

Besides that, don't trust what you get from Inline::C, the perlio.h header is included before your C code and most stdio functions are replaced by macros calling into perl own implementations (that not-too-unsurprisingly, do not work as expected either):

use strict; use warnings; use Inline 'C'; test_err(); __END__ __C__ #define xstr(s) str(s) #define str(s) #s void test_err() { (void)fprintf(stderr, "ERROR goes to " xstr(stderr) "\n"); } # here, it outputs: # ERROR goes to (*(*Perl_IStdIO_ptr(((PerlInterpreter *)Perl_get_conte +xt())))->pStderr)((*Perl_IStdIO_ptr(((PerlInterpreter *)Perl_get_cont +ext()))))

update: the funny thing is that when a subprocess is launched, perl file descriptors are the ones inherited:

open my $olderr, '>&STDERR'; # save STDERR my ($fh, $fn) = tempfile(); open STDERR, '>&', $fh; printf "fileno STDERR: %d\n", fileno(STDERR); print STDERR "foo!"; test_err(); system "perl -e die"; open STDERR, '>&', $olderr; # reset STDERR close $fh; open my $e, '<', $fn; my $err = <$e>; print "|$err|\n"; __END__ __C__ void test_err() { FILE *err = fdopen(2, "a+"); (void)fprintf (err, "ERROR"); } # fileno STDERR: 2 # |foo!Died at -e line 1. # | # ERROR


Comment on Re^3: STDERR going to string
Select or Download Code
Re^4: STDERR going to string
by philkime (Sexton) on Oct 11, 2011 at 15:29 UTC
    Hmm. On Windows I'm currently using a self-compiled 5.14.1 using the strawberry environment but I see the same with "real" strawberry 5.12.2. It seems that re-opening STDERR on windows decouples perl STDERR and the C library STDERR which I can't quite understand since I assumed that they were both fd=2 and I can redirect them both with 2>somewhere on the command line. It's just that perl doesn't see the C library STDERR as STDERR any more. The actual library is using really basic stdio ( fprint(stderr ... ) which is most certainly fd=2. Can perl and C have "different" STDERRs on windows?

      Can perl and C have "different" STDERRs on windows?

      No. There is only one STDERR on windows and it is always fileno 2. Perl wraps things so that stderr is a variable, but fileno 2 is always the original stderr.

      AFAIK, despite claims to the contrary, there is no way to get it to work on win32.

      If it was possible it would work already :)

        But then, why after redirecting STDERR, fileno(STDERR) is still 2? is it cheating?

        And why the Inline::C does example does not work even when the perlio.h redefines C stderr to point to some variable inside the perl runtime?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (12)
As of 2014-08-20 15:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (116 votes), past polls