[Bug libstdc++/70276] New: Writing to standard output concurrently through `std::cout` triggers a datarace

2016-03-19 Thread stefan at vectorfabrics dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70276

Bug ID: 70276
   Summary: Writing to standard output concurrently through
`std::cout` triggers a datarace
   Product: gcc
   Version: 4.9.4
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: stefan at vectorfabrics dot com
  Target Milestone: ---

Consider the following C++11 program:

  #include  
  #include  
  #include  

  int main() 
  { 
std::future future = 
  std::async(std::launch::async, []() { std::cout << "foo" << std::endl;
}); 
std::cout << "bar" << std::endl; 
future.wait(); 

return EXIT_SUCCESS; 
  }

This program exhibits a datarace for the member variable
`std::ios_base::_M_width` of `std::cout`.

For example, Pareon Verify reports (some details elided for clarity):

  [M0108] Data race(s) detected:
an object of size 272
is concurrently accessed by
the write in
  function ios_base::width at .../include/bits/ios_base.h:656
  called from function std::__ostream_insert at
.../include/bits/ostream_insert.h:102
  called from function std::operator<< at .../include/ostream:535
  called from function main at test.cpp:9
  ^^^ application start ^^^
performing 1 access of size 8 at an offset of 24 bytes from the start of
the object
and the read in
  function ios_base::width at .../include/bits/ios_base.h:645
  called from function std::__ostream_insert at
.../include/bits/ostream_insert.h:87
  called from function std::operator<< at .../include/ostream:535
  ...
  called from function execute_native_thread_routine at .../thread.cc:84
  ^^^ thread start ^^^
  called from function pthread_create
  ...
  called from function std::async at include/c++/4.9.2/future:1580
  called from function main at test.cpp:8
  ^^^ application start ^^^
performing 1 access of size 8 at an offset of 24 bytes from the start of
the object

Helgrind produces a similar (albeit somewhat more cryptic) message.

[Bug libstdc++/70276] Writing to standard output concurrently through `std::cout` triggers a datarace

2016-03-19 Thread stefan at vectorfabrics dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70276

--- Comment #1 from Stefan Holdermans  ---
A possible solution would be to make the accesses to `std::ios_base::_M_width`
from `std::ios_base::width()` and `std::ios_base::width(streamsize)` atomic.

Currently, these functions are defined by

  streamsize
  width() const
  { return _M_width; }

and

  streamsize
  width(streamsize __wide)
  {
streamsize __old = _M_width;
_M_width = __wide;
return __old;
  }

respectively.

[Bug libstdc++/70276] Writing to standard output concurrently through `std::cout` triggers a datarace

2016-03-19 Thread stefan at vectorfabrics dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70276

--- Comment #2 from Stefan Holdermans  ---
Note that the C++11 Standard (§27.4.1) prescribes that

"Concurrent access to a synchronized (§27.5.3.4) standard iostream object’s
formatted and unformatted input (§27.7.2.1) and output (§27.7.3.1) functions or
a standard C stream by multiple threads shall not result in a data race
(§1.10)."