NetBSD Problem Report #45587
From dholland@macaran.localdomain Mon Nov 7 14:24:01 2011
Return-Path: <dholland@macaran.localdomain>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
by www.NetBSD.org (Postfix) with ESMTP id C854163B8DB
for <gnats-bugs@gnats.NetBSD.org>; Mon, 7 Nov 2011 14:24:00 +0000 (UTC)
Message-Id: <20111107142416.C13A76E198@macaran.localdomain>
Date: Mon, 7 Nov 2011 09:24:16 -0500 (EST)
From: dholland@eecs.harvard.edu
Reply-To: dholland@eecs.harvard.edu
To: gnats-bugs@gnats.NetBSD.org
Subject: rewind(3) errno lossage
X-Send-Pr-Version: 3.95
>Number: 45587
>Category: lib
>Synopsis: rewind(3) errno lossage
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: standards-manager
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Nov 07 14:25:00 +0000 2011
>Last-Modified: Sun Oct 25 14:20:01 +0000 2020
>Originator: David A. Holland
>Release: NetBSD 5.99.49 (20110411)
>Organization:
>Environment:
System: NetBSD macaran 5.99.49 NetBSD 5.99.49 (MACARAN) #8: Mon Apr 11 19:54:18 EDT 2011 dholland@macaran:/usr/src/sys/arch/amd64/compile/MACARAN amd64
Architecture: x86_64
Machine: amd64
>Description:
The man page for rewind(3) says:
Since the rewind() function does not return an error code,
applications need to clear errno before calling it in order to
detect errors.
Since in general code is allowed to (and does) leave garbage in errno
when succeeding, any function that's going to allow this method of
error checking needs to take precautions to make sure it works.
Unfortunately, rewind doesn't.
If this is going to be a supported method of checking whether rewind
failed, it should save errno on entry and restore it except on
explicit failure.
Note that since rewind is supposed to clear the FILE's error flag, it
isn't possible to use ferror() to check for error, and it's defined by
C to return void, so I guess clearing and testing errno is the only
possible way to check for error... but maybe it shouldn't be supported
anyway. It's certainly not required by C99, although I haven't checked
POSIX.
>How-To-Repeat:
man page / code / standards reading.
>Fix:
save/restore errno as above.
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: lib-bug-people->standards-manager
Responsible-Changed-By: dholland@NetBSD.org
Responsible-Changed-When: Sun, 25 Oct 2020 02:03:12 +0000
Responsible-Changed-Why:
this is ultimately a standards question, so poke standards-manager for
advice.
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: lib/45587 (rewind(3) errno lossage)
Date: Sun, 25 Oct 2020 21:15:03 +0700
Date: Sun, 25 Oct 2020 02:03:12 +0000 (UTC)
From: dholland@NetBSD.org
Message-ID: <20201025020312.7FF741A923A@mollari.NetBSD.org>
The PR says:
so I guess clearing and testing errno is the only
possible way to check for error... but maybe it shouldn't
be supported anyway. It's certainly not required by C99,
although I haven't checked POSIX.
What POSIX says on this is...
Since rewind( ) does not return a value, an application
wishing to detect errors should clear errno, then call
rewind( ), and if errno is non-zero, assume an error has
occurred.
That paragraph ix "CX shaded" which means:
CX Extension to the ISO C standard
The functionality described is an extension to
the ISO C standard. Application developers may
make use of an extension as it is supported on
all POSIX.1-2017-conforming systems.
Back to the PR which also says:
If this is going to be a supported method of
checking whether rewind failed, it should save
errno on entry and restore it except on
explicit failure.
but I don't think that is correct.
Note that all POSIX says is "assume an error has occurred",
which unless some completely arbitrary event is happening
which looks unlikely, would mean any errors that occur while
rewind() is running. Errors occurring do not necessarily
always mean that the function failed.
Errors from the fseek() call are defined to be errors from
rewind(), all of them, except EINVAL which simply can't
happen (as defined by POSIX anyway) - that leaves errors
that occur during the file locking/unlocking, and I'd have
thought that if one of those generates an error, then that's
also an error from rewind() (something went terribly wrong
in that case). All that leaves, that I can think of, is if
a signal handler for a caught signal occurs while waiting for
the lock to be available (some other thread had fp() locked,
and this one needs to wait for that one to finish). If
that signal handler is corrupting errno then the program is
simply broken - that could cause far worse problems than
an apparent failure from rewind().
In short, unless there is an actual problem here, something
is actually failing, more than "man page / code / standards
reading." making it appear that there might be a problem,
I don't believe that there is anything here that needs to
be changed, and certainly a simple "save/restore errno as above"
would not be correct.
kre
ps: while POSIX does say that the error flag for the FILE *
gets cleared by rewind(), it doesn't say whether that is
intended to happen before or after the fseek() call (or
code to do the equivalent - in our case, it is an fseek()
call). Unless the C standard says which order (in which
case that would apply in POSIX as well, even without the
POSIX text being explicit on the issue) then there looks to
be a POSIX defect here - maybe a C standard defect as well.
This makes no practical difference, as while it would be
appealing to first clear the error flag, and then call
fseek() - meaning that the error flag might get set again
if the fseek() fails, that is clearly not what any implementations
have ever done, so if the stanrard(s?) ever got updated to
specify this, it would be to specify that the error flag is
cleared after the fseek() happens, not before.
>Unformatted:
(Contact us)
$NetBSD: gnats-precook-prs,v 1.4 2018/12/21 14:20:20 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.