This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libstdc++/12855] Thread safety problems in ios_base::Init


------- Additional Comments From peturr02 at ru dot is  2003-12-11 08:18 -------
I think the patch is fine in general, but this bit seems wrong:

*************** namespace std 
*** 80,86 ****
  
    ios_base::Init::Init()
    {
!     if (_S_ios_base_init == 0)
        {
  	// Standard streams default to synced with "C" operations.
  	_S_synced_with_stdio = true;
--- 80,86 ----
  
    ios_base::Init::Init()
    {
!     if (__exchange_and_add(&_S_references, 1) == 0)
        {
  	// Standard streams default to synced with "C" operations.
  	_S_synced_with_stdio = true;
*************** namespace std 
*** 110,124 ****
  	wcin.tie(&wcout);
  	wcerr.flags(ios_base::unitbuf);
  #endif
- 
- 	_S_ios_base_init = 1;
        }
-     ++_S_ios_base_init;
    }
  
    ios_base::Init::~Init()
    {
!     if (--_S_ios_base_init == 1)
        {
  	// Catch any exceptions thrown by basic_ostream::flush()
  	try
--- 110,121 ----
  	wcin.tie(&wcout);
  	wcerr.flags(ios_base::unitbuf);
  #endif
        }
    }
  
    ios_base::Init::~Init()
    {
!     if (__exchange_and_add(&_S_references, -1) == 1)
        {
  	
Currently, the constructor sets _S_ios_base_init to 2 on the first run. Each
call after that adds 1, and each call of the destructor subtracts 1. This is
done so that the streams are only constructed once.

It seems to me that with this patch, the first run of the constructor will
set _S_references to 1, but everything else is as before, so that:

#include <ios> // Note: not <iostream>
int main {
  { ios_base::Init i; } // Construct streams
  { ios_base::Init j; } // Constructs streams again
}

This can cause problems for programs that use static constructors to change
settings of the streams, or that perform IO in destructors or atexit()
functions.

There is a testcase that was supposed to check for this condition:
testsuite/27_io/objects/char/5.cc
testsuite/27_io/objects/wchar_t/5.cc
but it probably fails to catch it because <iostream> is included in the
precompiled header, so an Init object gets constructed before static_ob.

(IMHO neither <iostream> nor <cassert> should be included in the precompiled
headers since both can break obscure test cases, such as this one)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12855


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]