Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: STDERR going to string

by salva (Abbot)
on Oct 11, 2011 at 09:44 UTC ( #930768=note: print w/ replies, xml ) Need Help??


in reply to STDERR going to string

There is only one truly portable and robust way to do that: redirect STDERR to a temporal file before calling into XS and read it afterwards.

# Untested. Note also that this code will not handle special # cases as STDERR being closed, tied or attached to a file # descriptor different than 2. use autodie; use File::Temp qw(tempfile); open my $olderr, '>&STDERR'; # save STDERR my $fh = tempfile(); open STDERR, '>&', $fh; my $entry = Text::BibTeX::Entry->new($bib_entry); open STDERR, '>&', $olderr; # flush and reset STDERR seek($fh, 0, 0); my $err = do { local $/; <$fh> }; close $fh;


Comment on Re: STDERR going to string
Download Code
Re^2: STDERR going to string
by philkime (Sexton) on Oct 11, 2011 at 10:37 UTC
    I had something like this too but it doesn't work on Windows. Here is a stripped down example using Inline::C. On non-Windows (cygwin included), it outputs correctly: |ERROR| On Windows, it gives: || ERROR which shows you that the STDERR isn't being captured.
    use File::Temp qw(tempfile); use Inline C; open my $olderr, '>&STDERR'; # save STDERR my ($fh, $fn) = tempfile(); open STDERR, '>&', $fh; test_err(); open STDERR, '>&', $olderr; # reset STDERR close $fh; open my $e, '<', $fn; my $err = <$e>; print "|$err|\n"; __END__ __C__ void test_err() { (void)fprintf (stderr, "ERROR"); }
      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):

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

        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?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (20)
As of 2015-07-01 19:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (17 votes), past polls