perror() changes the orientation of stderr to byte-oriented mode if stderr is not oriented yet.
Craig Howland
howland@LGSInnovations.com
Fri Jul 6 06:59:00 GMT 2018
On 07/05/2018 08:49 AM, Corinna Vinschen wrote:
> On Jul 5 20:35, Takashi Yano wrote:
>> Hi Corinna,
>>
>> Thank you for checking.
>>
>> On Thu, 5 Jul 2018 13:19:21 +0200
>> Corinna Vinschen wrote:
>>> Yes, we need it, the entire operation, flushing and writing, must be
>>> cancel-safe and synchronized with other access to the stderr FILE.
>>>
>>> Comparing with FreeBSD, there's also something missing. After the
>>> write operation, the offset in the FILE structure is incorrect.
>>> Consequentially the __SOFF flag is reset to 0 last thing before
>>> unlocking the file:
>>>
>>> stderr->_flags &= ~__SOFF;
>> Do you mean these are necessary for both perror.c and psignal.c?
>> How about psiginfo() case?
> Well, as long as we use the method at hand, I think it's the right thing
> to do. However...
>
> ...I noticed that FreeBSD handles psignal differently. It writes the
> output immediately to STDERR_FILENO, rather than to stderr or
> fileno(stderr). It does also not call fflush or reset the _SOFF flag.
>
> OpenBSD uses this method for perror as well, no syncing with stderr,
> no cancel-safety.
>
> GLibc duplicates the file descriptor in perror, but writes immediately
> to STDERR_FILENO in psiginfo, or uses an internal variation of
> fprintf in psignal (thus potentially changing the orientation).
>
> Ok, I'm a bit more puzzled than before. What all this is missing is
> *consistency*.
>
> I really wonder how standards-compliant this is. For all three
> functions POSIX says something like "... shall print a message out on
> stderr ...". stderr is the stream and it's underlying descriptor, not
> necessarily STDERR_FILENO.
>
> If immediate writing to STDERR_FILENO is ok, we should simply call
> write(STDERR_FILENO) and be done with it. Just like BSDs and Linux,
> we don't even have to loop until all bytes have been written, none
> of the above does.
>
>
> Thoughts?
>
>
> Corinna
>
   POSIX defines all 3 functions with the same basic requirements, so it
certainly does seem like whatever we do ought to be done in the same way for all
3. (I suppose you could make an argument that perror() is C while the other 2
are not, allowing a possible difference there. But that doesn't seem like a
good idea.)
    I think that we're kind of stuck needing the fflush(). While I'd rather
just skip it, not calling it can provide end behavior that is clearly different
than perror()/etc. writing to the stream, itself, instead of calling write(2)
(even if only when it is not unbuffered).   That is, with a line or
fully-buffered stream, anything in the stream buffer already at the time
perror() is called should appear before the perror() output. If we don't flush,
the in-buffer data appear after. The fflush() is what ends up making it look
like we wrote to the stream using the more usual mechanism instead of write
directly. That is, I think that with the fflush(), the end result should be the
same as if we really were writing through the stream mechanism. (Although
there's a complication related to timing, which is why I'm saying "end result"
instead of "identical results."Â See below.)Â This means we would be statically
standard compliant, even if the underlying mechanism is doing an end run around
the usual internal stream write mechanisms.
    To put this into a different form:
lock stream stderr;
fflush(stderr);
write(fileno(stderr), string);
unlock stream stderr;
should produce the same end effect as
fputs(stderr, string);Â Â /* (effectively what perror() is required to end up
doing) */
in terms of the sequence of bytes which end up in the file.
   The former can produce a clear timing difference, however, although only
if the stream is fully buffered:Â the fputs() output might not appear until
something else is written (depending upon where the buffer fill happens to be),
while the former case forces string out right away. This seems impossible to
fix without returning to the full streams mechanism, but then we're back to the
complex 'don't change the orientation' problem we're trying to avoid. It seems
a small enough problem to accept, especially given the mess you're describing
for the other libraries.
    Along the same lines, since they are supposed to write to the stream,
strictly fileno(stderr) should be used, since it is possible for STDERR_FILENO
(a fixed constant) to be inaccurate. This point really is independent of the
fflush() question. (At least something seems easy to answer.)
            Craig
More information about the Newlib
mailing list