http://qs1969.pair.com?node_id=1132072


in reply to Redirecting/Restoring of Memory Files

Well, perldoc does say:
You may also, in the Bourne shell tradition, specify an EXPR beginning with ">&", in which case the rest of the string is interpreted as the name of a filehandle (or file descriptor, if numeric) to be duped (as dup(2))
And the UNIX system call dup works only with descriptors (files, pipes, FIFOs, sockets etc). So you probably shouldn't expect it to work with Perl data without an underlying descriptor.
The black hole goes away if I reopen using substr($s,length($s)) where $s is the original variable used to create the memory file handle.
Or if you reopen in append mode, as in
} else { open($fh1, '>>', \$s1) or die "Can't restore fh1"; }

Replies are listed 'Best First'.
Re^2: Redirecting/Restoring of Memory Files
by ELISHEVA (Prior) on Jun 26, 2015 at 07:10 UTC

    Your success with append mode might be Perl version/system dependent. On my macbook, I still get the black hole when I reopen in append mode. I've revised the script in the original post to also demonstrate what happens when one re-opens in append mode.

    I'm also not comfortable with the idea that "one shouldn't expect" a file handle to work with dup. As far as I know, Perl doesn't give me a way to tell if a file handle was created on a string.There is no way to gracefully degrade or warn the user if they hand my subroutine a file handle and it just happens to be backed with a string.

      Effectively i had no success in append mode (all tests on windows as above) as suggested by Anonymous.

      The possibility to open an handle to a string is in the Perl Faq and also the possibility to dup a filehandle is in the Perl Faq. Also, as you already said, is worth to read open and search for the phrase "Perl scalars".

      The crucial point seems to be spotted by Anonymous here above: the '>&' or '>&=' trick works only with descriptors and in your case ELISHEVA we have no descriptor:
      # perl -e ' open $h,">", \$s or die; print qq(fileno: [).fileno ($h).q +q(]\n);' fileno: [-1]
      And fileno doc says it explicitly:
      Returns the file descriptor for a filehandle, or undefined if the filehandle is not open. If there is no real file descriptor at the OS level, as can happen with filehandles connected to memory objects via open with a reference for the third argument, -1 is returned.
      So it seems only an hedge case worth to be inserted in the open documentation and in the relevant Faq

      As side note i remember the $^F or maximum file descriptor. How an handle opened on a reference acts in respect of this? is close_on_exec set in the right way? or this will result in zombie handles?
      Might be worth to clarify also this in the docs.

      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Your success with append mode might be Perl version/system dependent. On my macbook, I still get the black hole when I reopen in append mode.
      I mean
      open($fh1, '>', \ substr($s1, length($s1)) ) or die "Can't restore fh1";
      replace '>' with '>>' and \ substr($s1, length($s1)) with \$s1 and you'll get
      open($fh1, '>>', \$s1) or die "Can't restore fh1";
      I'm also not comfortable with the idea that "one shouldn't expect" a file handle to work with dup. As far as I know, Perl doesn't give me a way to tell if a file handle was created on a string.There is no way to gracefully degrade or warn the user if they hand my subroutine a file handle and it just happens to be backed with a string.
      Well I'm not saying that open is being reasonable here. IMO, yes, it should work, or at least warn if it doesn't. That being said, there is a way to tell the difference
      Returns the file descriptor for a filehandle, or undefined if the filehandle is not open. If there is no real file descriptor at the OS level, as can happen with filehandles connected to memory objects via "open" with a reference for the third argument, -1 is returned. - fileno