Author: sebor Date: Mon Mar 31 16:37:16 2008 New Revision: 643210 URL: http://svn.apache.org/viewvc?rev=643210&view=rev Log: 2008-03-31 Martin Sebor <[EMAIL PROTECTED]>
STDCXX-804 * include/ostream (ostream::_C_opfx): Detect and avoid flushing streams that are tied together or that share the same buffer to prevent deadlock or infinite recursion. Modified: stdcxx/trunk/include/ostream Modified: stdcxx/trunk/include/ostream URL: http://svn.apache.org/viewvc/stdcxx/trunk/include/ostream?rev=643210&r1=643209&r2=643210&view=diff ============================================================================== --- stdcxx/trunk/include/ostream (original) +++ stdcxx/trunk/include/ostream Mon Mar 31 16:37:16 2008 @@ -23,7 +23,7 @@ * implied. See the License for the specific language governing * permissions and limitations under the License. * - * Copyright 1994-2006 Rogue Wave Software. + * Copyright 1994-2008 Rogue Wave Software, Inc. * **************************************************************************/ @@ -294,12 +294,27 @@ inline basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::_C_opfx () { - basic_ostream* const __tie = this->tie (); + basic_ostream* __tie = this->tie (); - // flush tied stream only if its buffer is distinct from that - // of *this for greater efficiency and to to prevent a deadlock - if (__tie && this->good () && __tie->rdbuf () != this->rdbuf ()) - __tie->flush (); + if (__tie && this->good ()) { + + // detect and avoid flushing streams that are tied together + // or that share the same buffer to prevent deadlock or + // infinite recursion + const basic_ostream *__p0, *__p1; + + // traverse the list of tied streams looking for a cycle + for (__p0 = this, __p1 = this->tie (); __p0 && __p1; + __p0 = __p0->tie (), + __p1 = __p1->tie () ? __p1->tie ()->tie () : 0) + if (__p0 == __p1 || __p0->rdbuf () == __p1->rdbuf ()) { + __tie = 0; + break; + } + + if (__tie) + __tie->flush (); + } if (_C_is_sync ()) _RW::__rw_fflush (_RWSTD_STATIC_CAST (ios_base*, this), 0);