Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

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;

Replies are listed 'Best First'.
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?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://930768]
[Eily]: oh, boolean context uses the "" overload if no bool overload has been defined
[Eily]: (I wondered if overloading bool was actually necessary)
[Corion]: Yeah, you need bool to get a true value, and the rest to return the other value ;)
[choroba]: perl -wE '{package o; use Tie::Scalar; use parent -norequire => "Tie::StdScalar" ;sub FETCH { "x" x int rand 2}} tie my $x, "o" ; say $x for 1 .. 10'
[choroba]: for complete ness

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (9)
As of 2017-07-27 13:52 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (414 votes). Check out past polls.