New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PATCH] Ignore ENOTTY on open via the perlio buffer layer #14633
Comments
From @rurbanThis is a bug report for perl from rurban@cpanel.net, $ touch file Flags: Site configuration information for perl 5.21.10: Configured by rurban at Tue Mar 31 14:38:17 CEST 2015. Summary of my perl5 (revision 5 version 21 subversion 10) configuration: Locally applied patches: @INC for perl 5.21.10: Environment for perl 5.21.10: |
From @rurbanAnd the missing attachment: |
From @rurban0001-Ignore-ENOTTY-on-open-via-the-perlio-buffer-layer.patchFrom bc949af43e3d39078141495f7668cc8ba3a119c7 Mon Sep 17 00:00:00 2001
From: Reini Urban <rurban@cpanel.net>
Date: Fri, 3 Apr 2015 12:24:25 +0200
Subject: [PATCH] Ignore ENOTTY on open via the perlio buffer layer
$ touch file
$ perl -e'open(my $fh,"<","file") && print "$!\n";'
Inappropriate ioctl for device
When we push the buffer layer to PerlIO and do a failing isatty() check
which obviously fails on all normal files, reset the errno to 0
to ignore the wrong global ENOTTY.
See also http://stackoverflow.com/questions/1605195/inappropriate-ioctl-for-device
---
perlio.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git perlio.c perlio.c
index e5ebfd9..dd289e9 100644
--- perlio.c
+++ perlio.c
@@ -3815,11 +3815,15 @@ PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
{
PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
const int fd = PerlIO_fileno(f);
+ int reset_errno = 1;
if (fd >= 0 && PerlLIO_isatty(fd)) {
PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
+ reset_errno = 0;
}
if (*PerlIONext(f)) {
const Off_t posn = PerlIO_tell(PerlIONext(f));
+ /* if PerlIONext was isatty() and it obviously failed ignore the errno */
+ if (reset_errno && errno == ENOTTY) errno = 0;
if (posn != (Off_t) - 1) {
b->posn = posn;
}
--
2.1.4
|
From @bulk88On Fri Apr 03 03:29:12 2015, rurban@cpanel.net wrote:
Why are we zeroing -- |
The RT System itself - Status changed from 'new' to 'open' |
From @LeontOn Fri, Apr 3, 2015 at 4:01 PM, bulk88 via RT <perlbug-followup@perl.org>
Simply setting it to the old value is the more sensible thing IMO. Lots of Leon |
From @rurban
Right, this would be better. |
From @rurban0001-Ignore-ENOTTY-on-open-via-the-perlio-buffer-layer.patchFrom a6d31cb8807c260d86db586cbcdbf9096a9b5fc2 Mon Sep 17 00:00:00 2001
From: Reini Urban <rurban@cpanel.net>
Date: Fri, 3 Apr 2015 12:24:25 +0200
Subject: [PATCH] Ignore ENOTTY on open via the perlio buffer layer
$ touch file
$ perl -e'open(my $fh,"<","file") && print "$!\n";'
Inappropriate ioctl for device
When we push the buffer layer to PerlIO and do a failing isatty() check
which obviously fails on all normal files, restore errno
to ignore the wrong global ENOTTY.
See also http://stackoverflow.com/questions/1605195/inappropriate-ioctl-for-device
---
perlio.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git perlio.c perlio.c
index e5ebfd9..66d30fa 100644
--- perlio.c
+++ perlio.c
@@ -3815,11 +3815,17 @@ PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
{
PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
const int fd = PerlIO_fileno(f);
+ int reset_errno = 1;
+ dSAVE_ERRNO;
if (fd >= 0 && PerlLIO_isatty(fd)) {
PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
+ reset_errno = 0;
}
if (*PerlIONext(f)) {
const Off_t posn = PerlIO_tell(PerlIONext(f));
+ /* if PerlIONext was isatty() and it obviously failed, restore errno */
+ if (reset_errno && errno == ENOTTY)
+ RESTORE_ERRNO;
if (posn != (Off_t) - 1) {
b->posn = posn;
}
--
2.3.3
|
From @iabynOn Fri, Apr 03, 2015 at 04:08:19PM +0200, Leon Timmermans wrote:
I still don't understand why we're bothering to give $! a meaningful value -- |
From cm.perl@abtela.comLe 07/04/2015 12:52, Dave Mitchell a écrit :
because we might be in the process of reporting on a previously detected |
From @iabynOn Tue, Apr 07, 2015 at 06:17:29PM +0200, Christian Millour wrote:
But those are all for a completely different situation, where perl unless (open my $fh, "<", $file) { In those cases it is of course correct for perl to use dSAVE_ERRNO But in the case in this thread, we *know* we're making a system call, and This means C<errno>, hence C<$!>, is meaningful only I<immediately> if (open my $fh, "<", $filename) { -- |
From cm.perl@abtela.comLe 07/04/2015 20:27, Dave Mitchell a écrit :
rather, it *would* be correct for perl tu use dSAVE_ERRNO... Which it
We are making a system call that has its own way of signalling success.
This should be reworded to state that on success, the value of $! (or IIRC, the C standard states the same thing, that errno should not be |
From @iabynOn Wed, Apr 08, 2015 at 12:59:07PM +0200, Christian Millour wrote:
I don't think perl has ever guaranteed that perl functions documented After about 1 minute's effort I came up with this: open my $fh, "nosuchfile"; which prints Inappropriate ioctl for device I'm sure I could find many other perl system-ish functions that fail to
But atoi() is a library function not a system call, and isn't documented as -- |
From @ikegamiOn Wed, Apr 8, 2015 at 9:02 AM, Dave Mitchell <davem@iabyn.com> wrote:
Indeed, it's always allowed for the opposite. It's extensively and clearly |
From cm.perl@abtela.comLe 08/04/2015 16:28, Eric Brine a écrit :
You are correct. That has never been guaranteed. IMO more by oversight
No it is not. Please provide links. Most low level libraries are much more respectful of errno than you seem The initial value of errno at program startup is zero. Many library There are indeed exceptions but not that many There are a few library functions, like sqrt and atan, that return a To me a prime example of the evil of resetting/trashing $! on success is |
From @craigberryOn Wed, Apr 8, 2015 at 11:37 AM, Christian Millour <cm.perl@abtela.com> wrote:
POSIX says, "The setting of errno after a successful call to a The Linux man page says, "a function that succeeds is allowed to [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/errno.html |
From @iabynOn Wed, Apr 08, 2015 at 06:37:21PM +0200, Christian Millour wrote:
I think you are misreading the emphasis of that paragraph. I see it as: "library functions *might not* change errno to zero on success; therefore It's all about the latter; it's making no guarantee about the former.
I think you're conflating different classes of functions: 1. Functions that, on failure, set errno/$! to specify what failure; but Things like atoi or lc() fall into category 3; open() is category 1. But I don't see that the (mis)behaviour of require has any bearing on the -- |
From @ikegamiOn Wed, Apr 8, 2015 at 12:37 PM, Christian Millour <cm.perl@abtela.com>
perldoc -v '$!' It's repeated 5 times! |
From @LeontOn Wed, Apr 8, 2015 at 7:06 PM, Dave Mitchell <davem@iabyn.com> wrote:
Actually, POSIX says «No function in this volume of IEEE Std 1003.1-2001 Leon |
From cm.perl@abtela.comLe 08/04/2015 19:06, Dave Mitchell a écrit :
Why on earth should you read it that way ? Unlike Posix or Linux which,
As I read it, it does. And I do wish Posix and Linux made such
The problem is that if successfull function or system calls are allowed eval {...; maybe in the process of unwinding the stack in the eval block some Or consider the following (silly) sub logdie { if open, print, or the implicit close clear/trash errno on success, and eval { again, what do you get in $e ? I would claim that the assumption that library functions and system I wonder how many core and CPAN tests would fail with a Perl linked To me the bottom line is that there are good reasons to try and preserve |
From @iabynOn Thu, Apr 09, 2015 at 03:06:25AM +0200, Christian Millour wrote:
The whole purpose of that paragraph is to warn people not to assume that It is not a paragraph whose main intent is to promise that you can rely on
But that's an absurd example. Maybe in the process of unwinding the stack
Again, what happens if logdie trashes errno on *failure*?
And once again you're conflating non-$! functions and $!-setting system
If they fail, then they are buggy. -- |
From cm.perl@abtela.comLe 09/04/2015 12:34, Dave Mitchell a écrit :
Not a problem with careful coding. I do this constantly. Irrelevant sub cleanup_temporary_files { So yes, there is a need to be attentive to the impact of ones own code What I don't want to do is wrap each and every invocation of a system Anyway, aren't you basically stating that it is unreasonable to 'die $!' ? |
From @iabynOn Thu, Apr 09, 2015 at 05:47:13PM +0200, Christian Millour wrote:
So your plan is that any code *anywhere* that *might* set $! needs to be My plan is that you should only make use of $! directly after a failed I know which I prefer.
No, it's perfectly ok to "die $!". I'm stating that after you trap an sub DESTROY { open my $fh, "/nosuchfile" } gives: err=No such process at /home/davem/tmp/p line 5. The die has worked correctly, but $! has changed during the stack unwind. -- |
From cm.perl@abtela.comLe 09/04/2015 18:46, Dave Mitchell a écrit :
Oh please ! I was only explaining how I would handle your objection,
Fair enough. I really wish I were savvy enough to experiment with a
Sure. But the problem with this is that even if you 'die $!' what you My stance on this might stem from a (maybe misguided) need to deal with eval { some_sub_that_might_die_or_croak; 1 } or do { The problem with I_can_make_sense_of_this_error_string() above is that Anyway. Our exchange started on my part as an honest attempt to address |
From dennis@kaarsemaker.netOn vr, 2015-04-10 at 00:14 +0200, Christian Millour wrote:
At least on linux succesful calls to e.g. malloc simply don't touch errno is *not* for checking whether an error occured, and any attempt to dennis@spirit:~$ cat foo.c int main(int argc, char **argv) { -- |
From cm.perl@abtela.comTL;DR: There are good reasons why Perl should be polite wrt to $! and Le 10/04/2015 09:21, Dennis Kaarsemaker a écrit :
I certainly hope so. But where in linux malloc documentation is it Le 08/04/2015 19:05, Craig A. Berry a écrit : The way I read [2], linux malloc is indeed allowed to set errno to Similarly, the documentation for malloc and write in [1] make no claim In practice however, I believe Leon has it right : Le 09/04/2015 01:58, Leon Timmermans a écrit : The uncertainty is galling though, and has dismal consequences. First, most of Perl is written on the (AFAIK) undocumented and untested Second, it leads to the impression that 'errno cannot be trusted unless But is errno really that volatile ? Who modifies errno anyway ? Wouldn't it be nice it Perl offered explicitely the guarantee that its I understand I might be alone in wishing such. However it irks me that But this is Perl, and however misguided my attempts might look, I should Incidentally, I find it interesting to note that it is those possibly earlier in this thread : Le 08/04/2015 19:06, Dave Mitchell a écrit :
I don't buy this 'conflation' argument. When writing code in Perl, I To me, cases 1 and 3 above should behave identically, in the sense that BTW,here is perldoc -v '$!': This means "errno", hence $!, is if (open my $fh, "<", $filename) { Here, *meaningless* means that $! may be unrelated to the I understand *meaningful* above as *related to the outcome of the There is however a problem with the definition of *meaningless*. Because That would allow for instance Perl open() to reset $! on success. I have demonstrated (#119555) that such a reset is *BAD* (action at a Le 09/04/2015 12:34, Dave Mitchell a écrit :
Not the same but I performed a quick and dirty experiment by setting blead(unx) $ ./perl -e 'eval { Hmmm. It would seem that Perl actually *depends* on malloc() refraining I am very tempted to generalize this finding to other systems calls ;-) IMO there are two possibly legitimate objections against having Perl |
From @pjcjI'm not sure how this thread has got so long because the basics are The <errno.h> header file defines the integer variable errno, which is A common mistake is to do if (somecall() == -1) { where errno no longer needs to have the value it had upon return from if (somecall() == -1) { That is clear, no? On Wed, Apr 15, 2015 at 06:57:55PM +0200, Christian Millour wrote:
There is no uncertainty. If you look at errno other than when it is
I don't think perl was written on that assumption, but it may only be But your assertion of what well behaved means here is incorrect.
A system call may, for example, make other system calls, some of which
That's not just an impression, it's a fact - for certain definitions of
This is the same incorrect definition of well behaved.
After the *failed* call - yes. This is not overly wary, it is correct.
It could be.
That may be true, but it is not useful information. What are you going
This is a valid argument, but it is a different argument. Is this the -- |
From @rurbanOn 04/16/2015 01:18 PM, Paul Johnson via RT wrote:
No. It is very surprising that a call to open a buffered file will set OpenBSD and then NetBSD recently even went to rewrite realloc() because |
From @craigberryOn Wed, Apr 15, 2015 at 11:57 AM, Christian Millour <cm.perl@abtela.com> wrote:
You're asking Perl to make a guarantee that C library maintainers and Thus your proposal to save and restore errno for every Perl op could, [1] Section 7.5 of <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf> |
From @ikegamiOn Fri, Apr 17, 2015 at 3:53 PM, Craig A. Berry <craig.a.berry@gmail.com>
Sounds like a straw man to me. 1) $! doesn't have to start indeterminate, local $! = 0; |
From @craigberryOn Fri, Apr 17, 2015 at 3:01 PM, Eric Brine <ikegami@adaelis.com> wrote:
Sure, we could assume the C standards committee doesn't know what it's
But this whole thread has been about the desire to avoid having to do that. |
From @ikegamiOn Fri, Apr 17, 2015 at 4:55 PM, Craig A. Berry <craig.a.berry@gmail.com>
I didn't suggest any such thing. , take matters into our own hands, and clear errno at thread start-up while we're initializing the interpreter context. I didn't suggest any such thing.
Really? It's the only way preserving $! on success can be useful. |
From @ikegamiOn Fri, Apr 17, 2015 at 4:55 PM, Craig A. Berry <craig.a.berry@gmail.com>
Are you really claiming that applications shouldn't change errno? |
From @craigberryOn Fri, Apr 17, 2015 at 4:08 PM, Eric Brine <ikegami@adaelis.com> wrote:
In the context I outlined of errno being, according to C11,
You've really lost me now. Either there is some sort of communication |
From @craigberryOn Fri, Apr 17, 2015 at 4:11 PM, Eric Brine <ikegami@adaelis.com> wrote:
Uh, what? I actually never said anything about applications. The |
From @ikegamiOn Fri, Apr 17, 2015 at 5:57 PM, Craig A. Berry <craig.a.berry@gmail.com>
The conversation is about changing the behaviour of $!. I never mentioned
Feel free to provide a counter example. |
From cm.perl@abtela.comLe 16/04/2015 13:17, Paul Johnson a écrit :
Yes but it is an implementation detail (a pretty major one, I agree).
Nope. Absolutely not. We can make The crux of the matter is maybe that, at this point, there is no stated
Yes.
No.
Let's try. Terminology :It is difficult to come up with a terminology completely devoid of - Polite : guaranteed not to alter So, the concept of Politeness, and the Polite and Impolite qualifiers, For the sake of precision and disambiguation let us use different - Courteous: guaranteed not to alter errno (and syserrno) on success. So, the concept of Courteousness, and the Courteous and Discourteous Some of what follows is an exploration of the relationships between What I'd like :I'd like eval { [ Why ? Because, for programmatic error handling, it is much safer and Before anyone starts, the problem of *unsuccessful* destructors is And before you turn away in disgust yelling about the unreasonableness There is no denying though that the assumption stated in CAPITALS above That said, turning any Perl code fragment into a guaranteed polite one { This of course may be overkill if the code fragment was already polite And what about destructors that are not under direct control of the If Perl was polite, or possibly mostly polite, with documented Politeness and CourteousnessNow, who manipulates Clearly the politeness of Perl depends a lot on the courteousness of Path to PolitenessA completely courteous underlying library would probably lead As pointed out expertly by Craig and others, the relevant standards and In addition, and quoting perlclib :
So Perl has some easy means to insulate itself from some potentially These same mechanisms could be used, with similar costs, for Not all library functions are abtracted or reimplemented though, as was It might be guesswork and wishful thinking but I believe that politeness Is Politeness desirable ?For the reasons outlined previously, I obviously believe that Politeness At the very least I believe that it is useful to put a name to the Interest in Politeness provides a fresh outlook on Perl core code, which A policy for Politeness ?At present the politeness of perl operators and builtins is unspecified. A Politeness policy might start by introducing the concepts of From there we might gradually turn other Perl operators and builtins --Christian |
From cm.perl@abtela.comLe 17/04/2015 21:53, Craig A. Berry a écrit :
I am deeply sorry about this erroneous and misleading wording. What I
I am slowly realizing that and thank you for your time and expertise. I
I do not expect errno to ever be zero because the only time I will ever
True
Not really because I am not using the value of errno itself as the
|
From @tonycozOn Tue Apr 07 11:27:57 2015, davem wrote:
As Dave and others have said, we explicitly document that $! is meaningless after a successful operation. Rejecting this patch. Tony |
@tonycoz - Status changed from 'open' to 'rejected' |
Migrated from rt.perl.org#124232 (status was 'rejected')
Searchable as RT124232$
The text was updated successfully, but these errors were encountered: