t/io/errno.t failures with stdio layer in IRIX #14557
(IRIX 6.5 IRIX64)
There's something fishy about the stdio layer. The 'stdio' half of t/io/errno.t fails,
But what fails, for example, is:
(which is what t/harness does, basicallt) which fails with:
Just guessing but some well-placed SETERRNO(0,0) is missing, to zap the obvious ENOENT?
(as of blead http://perl5.git.perl.org/perl.git/commit/94a0894418670e8bdd2c1d63e76a77225365995d)
Some more debugging. Here's a minimal failure case (run in the t subdirectory):
jhi@irix$ echo test | env PERLIO=stdio ../perl -I../lib -e '<>; print $!'
Here's a minimal success case:
jhi@irix$ echo test | env PERLIO=stdio ../perl -e '<>; print $!'
Curious, isn't it? The -I../lib is necessary.
Also needed are PERLIO=stdio, and the <>.
(One can do undef $! or $!=0 before the <>, but it makes no difference.)
So I did some system call tracing, par(1) in IRIX. The logs attached.
It seems that with the -Ilib there are two groups of open() calls that fail and set the errno:
The read(0, ...) from stdin (the readline) happens just before the second group of open() calls.
(The first group is obviously some -I magic, checking whether per-version per-arch dirs exist.)
But the second group is equally obviously locale-related.
Not that it's anything to with Perl's locale-code, mind. It seems to be trying to open some operating system level message catalog, for some unknown reason, because the previous system call looks like
11mS[ 0] : syssgi(0x5c, 0x1, 0, 0x2f, 0x101d7ea0, 0x101d7ebb) = 0
syssgi(0x5c, ...) seems to be gloriously undocumented... but purely guessing by its name
#define SGI_RXEV_GET 92
it could be to do with the par(1) tracing itself. But in any case, it returned zero.
Looks like the stat() calls were red herrings; they were not setting the errno.
What was setting it is something in the IRIX stdio implementation. The rabbit hole was
pp_readline -> do_readline -> sv_gets -> PerlIO_getc -> PerlIO_read -> PerlIOStdio_read
And in the PerlIOStdio_read both the branches:
* the count == 1 branch which uses stdio fgetc()
* the non-1-else branch which uses stdio fread()
got their errno=0 stomped on with errno=2 (ENOENT) with fgetc() and fread() respectively,
echo | env PERLIO=stdio ../perl -I../lib -e '<>; print $!'
echo test | env PERLIO=stdio ../perl -I../lib -e '<>; print $!'
Now worked around with commit bdae417. Before the change "No such file or directory" got printed, after, not.