This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libstdc++/12855] Thread safety problems in ios_base::Init
- From: "bkoz at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 10 Dec 2003 00:17:59 -0000
- Subject: [Bug libstdc++/12855] Thread safety problems in ios_base::Init
- References: <20031031094301.12855.peturr02@ru.is>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From bkoz at gcc dot gnu dot org 2003-12-10 00:17 -------
This would at least remove the corruption of _S_ios_base_init. I figure this is
less useful than the _S_once approach, but necessary no matter what.
Thoughts? I would like to fix this up for 3.4, regardless of how hypothetical
this issue is, or appears to be. I think this issue could, in fact, appear in
practice, either with dlopen or inadvertent (but legal) use of ios_base::Init.
-benjamin
-----
2003-12-09 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/12855
* include/bits/ios_base.h (_Callback_list): _M_refcount to
_M_references.
(Init::_S_ios_base_init): Change to _S_references, make atomic.
* src/ios.cc: Adjust definition.
* src/ios_init.cc (ios_base::Init::Init): Use __exchange_and_add.
(ios_base::Init::~Init): Same.
* testsuite/27_io/ios_base/cons/assign_neg.cc: Adjust line numbers.
* testsuite/27_io/ios_base/cons/copy_neg.cc: Same.
Index: include/bits/ios_base.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/ios_base.h,v
retrieving revision 1.34
diff -c -p -r1.34 ios_base.h
*** include/bits/ios_base.h 12 Oct 2003 10:12:08 -0000 1.34
--- include/bits/ios_base.h 10 Dec 2003 00:14:44 -0000
*************** namespace std
*** 428,445 ****
_Callback_list* _M_next;
ios_base::event_callback _M_fn;
int _M_index;
! _Atomic_word _M_refcount; // 0 means one reference.
_Callback_list(ios_base::event_callback __fn, int __index,
_Callback_list* __cb)
! : _M_next(__cb), _M_fn(__fn), _M_index(__index), _M_refcount(0) { }
void
! _M_add_reference() { __atomic_add(&_M_refcount, 1); }
// 0 => OK to delete.
int
! _M_remove_reference() { return __exchange_and_add(&_M_refcount, -1); }
};
_Callback_list* _M_callbacks;
--- 428,445 ----
_Callback_list* _M_next;
ios_base::event_callback _M_fn;
int _M_index;
! _Atomic_word _M_references; // 0 means one reference.
_Callback_list(ios_base::event_callback __fn, int __index,
_Callback_list* __cb)
! : _M_next(__cb), _M_fn(__fn), _M_index(__index), _M_references(0) { }
void
! _M_add_reference() { __atomic_add(&_M_references, 1); }
// 0 => OK to delete.
int
! _M_remove_reference() { return __exchange_and_add(&_M_references, -1); }
};
_Callback_list* _M_callbacks;
*************** namespace std
*** 493,506 ****
~Init();
// NB: Allows debugger applications use of the standard streams
! // from operator new. _S_ios_base_init must be incremented in
! // _S_ios_create _after_ initialization is completed.
static bool
! _S_initialized() { return _S_ios_base_init; }
private:
! static int _S_ios_base_init;
! static bool _S_synced_with_stdio;
};
// [27.4.2.2] fmtflags state functions
--- 493,505 ----
~Init();
// NB: Allows debugger applications use of the standard streams
! // from operator new.
static bool
! _S_initialized() { return _S_references > 0; }
private:
! static _Atomic_word _S_references;
! static bool _S_synced_with_stdio;
};
// [27.4.2.2] fmtflags state functions
Index: src/ios.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/ios.cc,v
retrieving revision 1.51
diff -c -p -r1.51 ios.cc
*** src/ios.cc 17 Oct 2003 14:47:30 -0000 1.51
--- src/ios.cc 10 Dec 2003 00:14:44 -0000
*************** namespace std
*** 107,113 ****
const int ios_base::_S_local_word_size;
! int ios_base::Init::_S_ios_base_init = 0;
bool ios_base::Init::_S_synced_with_stdio = true;
--- 107,113 ----
const int ios_base::_S_local_word_size;
! _Atomic_word ios_base::Init::_S_references;
bool ios_base::Init::_S_synced_with_stdio = true;
Index: src/ios_init.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/ios_init.cc,v
retrieving revision 1.1
diff -c -p -r1.1 ios_init.cc
*** src/ios_init.cc 17 Oct 2003 14:47:30 -0000 1.1
--- src/ios_init.cc 10 Dec 2003 00:14:44 -0000
*************** 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)
{
// Catch any exceptions thrown by basic_ostream::flush()
try
Index: testsuite/27_io/ios_base/cons/assign_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc,v
retrieving revision 1.6
diff -c -p -r1.6 assign_neg.cc
*** testsuite/27_io/ios_base/cons/assign_neg.cc 12 Oct 2003 10:12:09 -0000 1.6
--- testsuite/27_io/ios_base/cons/assign_neg.cc 10 Dec 2003 00:14:45 -0000
*************** void test01()
*** 41,45 ****
io1 = io2;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
! // { dg-error "is private" "" { target *-*-* } 746 }
// { dg-error "operator=" "" { target *-*-* } 0 }
--- 41,45 ----
io1 = io2;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
! // { dg-error "is private" "" { target *-*-* } 745 }
// { dg-error "operator=" "" { target *-*-* } 0 }
Index: testsuite/27_io/ios_base/cons/copy_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc,v
retrieving revision 1.6
diff -c -p -r1.6 copy_neg.cc
*** testsuite/27_io/ios_base/cons/copy_neg.cc 12 Oct 2003 10:12:09 -0000 1.6
--- testsuite/27_io/ios_base/cons/copy_neg.cc 10 Dec 2003 00:14:45 -0000
*************** void test02()
*** 41,45 ****
test_base io2 = io1;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
! // { dg-error "is private" "" { target *-*-* } 743 }
// { dg-error "copy constructor" "" { target *-*-* } 0 }
--- 41,45 ----
test_base io2 = io1;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
! // { dg-error "is private" "" { target *-*-* } 742 }
// { dg-error "copy constructor" "" { target *-*-* } 0 }
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12855