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);


Reply via email to