Why does opening an undef not fail?
Asked Answered
E

1

9

This code dies as I expect it to:

use strict;
use warnings;

open my $fh, "<", "" or die $!;

But this does not:

use strict;
use warnings;

open my $fh, "<", undef or die $!;

What is going on here?

Eleazar answered 20/4, 2017 at 14:2 Comment(0)
E
17

The open function has lots of little quirks, this is one of them:

As a special case the three-argument form with a read/write mode and the third argument being "undef":

open(my $tmp, "+>", undef) or die ...

opens a filehandle to an anonymous temporary file. Also using "+<" works for symmetry, but you really should consider writing something to the temporary file first. You will need to seek() to do the reading.

Although, as ysth notes in the comments, the documentation strongly suggests that this should only happen for "+<" and ">+" modes. I believe this is the code that implements the behavior. It does not check the mode. I do not know if this is a bug or not, but will report back after talking to P5P.

PerlIO *
PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
             int imode, int perm, PerlIO *f, int narg, SV **args)
{
    if (!f && narg == 1 && *args == &PL_sv_undef) {
        if ((f = PerlIO_tmpfile())) {
            if (!layers || !*layers)
                layers = Perl_PerlIO_context_layers(aTHX_ mode);
            if (layers && *layers)
                PerlIO_apply_layers(aTHX_ f, mode, layers);
        }
    }

Apparently, the documentation was fixed in blead perl in November:

diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index 18bb4654e1..1e32cca6dd 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -4405,9 +4405,9 @@ argument being L<C<undef>|/undef EXPR>:

     open(my $tmp, "+>", undef) or die ...

-opens a filehandle to an anonymous temporary file.  Also using C<< +< >>
-works for symmetry, but you really should consider writing something
-to the temporary file first.  You will need to
+opens a filehandle to a newly created empty anonymous temporary file.
+(This happens under any mode, which makes C<< +> >> the only useful and
+sensible mode to use.)  You will need to
 L<C<seek>|/seek FILEHANDLE,POSITION,WHENCE> to do the reading.

 Perl is built using PerlIO by default.  Unless you've
Eleazar answered 20/4, 2017 at 14:2 Comment(3)
yes, this is what is happening, but the doc seems to be wrong, since this is clearly not a read/write modeStoddart
the read/write mode is +> AND the third argument is undef. It is just worded poorlyApthorp
Hmm, good point @ysth, I glossed over it in my anger. I read it as read or write mode, but it is pretty explicit that it is for read+write or write+read modes. So, either this is a bug or poorly documented.Eleazar

© 2022 - 2024 — McMap. All rights reserved.