public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream
@ 2023-01-26 16:56 lavr at ncbi dot nlm.nih.gov
  2023-01-26 17:07 ` [Bug libstdc++/108561] " redi at gcc dot gnu.org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: lavr at ncbi dot nlm.nih.gov @ 2023-01-26 16:56 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

            Bug ID: 108561
           Summary: std::endl causes a flush on a bad stream
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lavr at ncbi dot nlm.nih.gov
  Target Milestone: ---

As implemented:

  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>&
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

this code can cause flush() to be called for a stream that has gone bad during
the execution of put().  Note that put() constructs a sentry, which if it threw
an exception, would case the stream to get a badbit (the most severe case; but
other unsuccessful sentry construction errors fit the same pattern).  On the
other hand, flush() does not check for any such things -- there's no sentry
construction -- instead, it just blindly calls the underlying stream buffer's
pubsync().  The bottom line result is that the failed output is missing yet the
flush is still attempted, but the expected behavior is that the output should
be _followed_ by the flush.  Otherwise, the order of the expected I/O is wrong
(the flush appears out of order when put() failed).

A fix would be to do something like this:

__os = __os.put(__os.widen('\n');
return __os ? flush(__os) : __os;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/108561] std::endl causes a flush on a bad stream
  2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
@ 2023-01-26 17:07 ` redi at gcc dot gnu.org
  2023-01-26 17:32 ` lavr at ncbi dot nlm.nih.gov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2023-01-26 17:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The standard doesn't say anything about not flushing if the put (or any
previous output function) failed.

> Calls os.put(os.widen(’\n’)), then os.flush().

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/108561] std::endl causes a flush on a bad stream
  2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
  2023-01-26 17:07 ` [Bug libstdc++/108561] " redi at gcc dot gnu.org
@ 2023-01-26 17:32 ` lavr at ncbi dot nlm.nih.gov
  2023-01-26 17:45 ` lavr at ncbi dot nlm.nih.gov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: lavr at ncbi dot nlm.nih.gov @ 2023-01-26 17:32 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

--- Comment #2 from lavr at ncbi dot nlm.nih.gov ---
Indeed, it does not.  But the reason the endl manipulator is there, is to flush
_after_ '\n'.  If the stream has gone bad in between, it is the gray area, but
for the output device (the stream buffer), it's an intentional corruption.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/108561] std::endl causes a flush on a bad stream
  2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
  2023-01-26 17:07 ` [Bug libstdc++/108561] " redi at gcc dot gnu.org
  2023-01-26 17:32 ` lavr at ncbi dot nlm.nih.gov
@ 2023-01-26 17:45 ` lavr at ncbi dot nlm.nih.gov
  2023-01-26 17:50 ` redi at gcc dot gnu.org
  2023-01-27 12:50 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: lavr at ncbi dot nlm.nih.gov @ 2023-01-26 17:45 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

--- Comment #3 from lavr at ncbi dot nlm.nih.gov ---
Also, the standard seems to mention that flush() is an "unformatted output
function", meaning it is supposed to build and check a sentry object (which in
case of a bad stream, would fail, so it's not going to proceed with pubsync()).
 In GCC implementation, the sentry is not constructed, and the comment in the
source code seems to contradict with the standard:

      // basic_ostream::flush() is *not* an unformatted output function.
      ios_base::iostate __err = ios_base::goodbit;
      __try
        {
          if (this->rdbuf() && this->rdbuf()->pubsync() == -1)
            __err |= ios_base::badbit;
        }

If the flush() implementation followed the standard, then the implementation of
endl could be left alone (unconditional chained flush).

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/108561] std::endl causes a flush on a bad stream
  2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
                   ` (2 preceding siblings ...)
  2023-01-26 17:45 ` lavr at ncbi dot nlm.nih.gov
@ 2023-01-26 17:50 ` redi at gcc dot gnu.org
  2023-01-27 12:50 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2023-01-26 17:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
That changed with https://cplusplus.github.io/LWG/issue581 which I implemented
for GCC 12 in r12-1817-gf8c5b542f6cb6a so I guess you're looking at gcc-11 or
older.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/108561] std::endl causes a flush on a bad stream
  2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
                   ` (3 preceding siblings ...)
  2023-01-26 17:50 ` redi at gcc dot gnu.org
@ 2023-01-27 12:50 ` redi at gcc dot gnu.org
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2023-01-27 12:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108561

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |12.0
         Resolution|---                         |FIXED
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think this can be closed. std::endl is doing exactly what it's supposed to
do, and ostream::flush has been fixed (15 years late) so that it won't flush a
bad stream.

I didn't backport the fix to gcc-11 and earlier because it *is* a change in
observable behaviour, although maybe it's unequivocally a good change and would
make sense to backport.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-01-27 12:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-26 16:56 [Bug libstdc++/108561] New: std::endl causes a flush on a bad stream lavr at ncbi dot nlm.nih.gov
2023-01-26 17:07 ` [Bug libstdc++/108561] " redi at gcc dot gnu.org
2023-01-26 17:32 ` lavr at ncbi dot nlm.nih.gov
2023-01-26 17:45 ` lavr at ncbi dot nlm.nih.gov
2023-01-26 17:50 ` redi at gcc dot gnu.org
2023-01-27 12:50 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).