This is the mail archive of the gcc-patches@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]

libio plays loose with locking


In many places inside iostream the call to isfx is missing, so that the
stream remains locked after the function returns.  You'll only notice it
when you use threads.


1999-08-05  Andreas Schwab  <schwab@suse.de>

	* iostream.cc: Add missing calls to isfx and setup a cleanup
	region for the locked stream.
	* iostream.h: Likewise.
	* isgetline.cc: Likewise.
	* isgetsb.cc: Likewise.
	* isscan.cc: Likewise.

Index: iostream.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/iostream.cc,v
retrieving revision 1.9
diff -u -a -r1.9 iostream.cc
--- iostream.cc	1998/02/24 20:09:51	1.9
+++ iostream.cc	1999/08/05 14:27:55
@@ -71,6 +71,8 @@
 istream& istream::get(char& c)
 {
     if (ipfx1()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	int ch = _strbuf->sbumpc();
 	if (ch == EOF) {
 	  set(ios::eofbit|ios::failbit);
@@ -80,6 +82,8 @@
 	  c = (char)ch;
 	  _gcount = 1;
 	}
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     else
       _gcount = 0;
@@ -102,10 +106,12 @@
 {
     _gcount = 0;
     if (ipfx1()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	register streambuf* sb = _strbuf;
 	if (delim == EOF) {
 	    _gcount = sb->ignore(n);
-	    return *this;
+	    goto unlock;
 	}
 	for (;;) {
 #if 0
@@ -122,6 +128,9 @@
 	    if (ch == delim)
 		break;
 	}
+    unlock:
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     return *this;
 }
@@ -129,9 +138,13 @@
 istream& istream::read(char *s, streamsize n)
 {
     if (ipfx1()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	_gcount = _strbuf->sgetn(s, n);
 	if (_gcount != n)
 	    set(ios::failbit|ios::eofbit);
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     else
       _gcount = 0;
@@ -184,11 +197,15 @@
 istream& istream::operator>>(char& c)
 {
     if (ipfx0()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	int ch = _strbuf->sbumpc();
 	if (ch == EOF)
 	    set(ios::eofbit|ios::failbit);
 	else
 	    c = (char)ch;
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     return *this;
 }
@@ -200,6 +217,8 @@
   int w = width(0);
   if (ipfx0())
     {
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				_strbuf);
       register streambuf* sb = _strbuf;
       for (;;)
 	{
@@ -219,6 +238,8 @@
 	}
       if (p == ptr)
 	set(ios::failbit);
+      isfx();
+      _IO_cleanup_region_end (0);
     }
   *p = '\0';
   return *this;
@@ -234,6 +255,9 @@
 {
     if (!stream.ipfx0())
       return 0;
+    int retval;
+    _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+			      stream._strbuf);
     register streambuf* sb = stream.rdbuf();
     int base = 10;
     int ndigits = 0;
@@ -254,7 +278,7 @@
 	    ch = sb->sbumpc();
 	    if (ch == EOF) {
 		val = 0;
-		return 1;
+		goto unlock;
 	    }
 	    if (ch == 'x' || ch == 'X') {
 		base = 16;
@@ -290,19 +314,26 @@
 	    if (ndigits == 0)
 		goto fail;
 	    else
-		return 1;
+		goto unlock;
 	}
 	ndigits++;
 	val = base * val + digit;
 	ch = sb->sbumpc();
     }
-    return 1;
+  unlock:
+    retval = 1;
+    goto out;
   fail:
     stream.set(ios::failbit);
-    return 0;
+    retval = 0;
+    goto out;
   eof_fail:
     stream.set(ios::failbit|ios::eofbit);
-    return 0;
+    retval = 0;
+  out:
+    stream.isfx();
+    _IO_cleanup_region_end (0);
+    return retval;
 }
 
 #define READ_INT(TYPE) \
@@ -334,6 +365,8 @@
 {
     if (ipfx0())
       {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 #if _G_HAVE_LONG_DOUBLE_IO
 	scan("%Lg", &x);
 #else
@@ -341,6 +374,8 @@
 	scan("%lg", &y);
 	x = y;
 #endif
+	isfx();
+	_IO_cleanup_region_end (0);
       }
     return *this;
 }
@@ -348,20 +383,34 @@
 istream& istream::operator>>(double& x)
 {
     if (ipfx0())
+      {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	scan("%lg", &x);
+	isfx();
+	_IO_cleanup_region_end (0);
+      }
     return *this;
 }
 
 istream& istream::operator>>(float& x)
 {
     if (ipfx0())
+      {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	scan("%g", &x);
+	isfx();
+	_IO_cleanup_region_end (0);
+      }
     return *this;
 }
 
 istream& istream::operator>>(register streambuf* sbuf)
 {
     if (ipfx0()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	register streambuf* inbuf = rdbuf();
 	// FIXME: Should optimize!
 	for (;;) {
@@ -375,6 +424,8 @@
 		break;
 	    }
 	}
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     return *this;
 }
@@ -789,8 +840,8 @@
       if (flags() & ios::left && padding > 0) // Left adjustment.
 	if (_IO_padn(sbuf, fill_char, padding) != padding)
 	  set(ios::badbit);
-      osfx();
      failed:
+      osfx();
       _IO_cleanup_region_end (0);
     }
   return *this;
Index: iostream.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/iostream.h,v
retrieving revision 1.3
diff -u -a -r1.3 iostream.h
--- iostream.h	1997/09/16 16:00:28	1.3
+++ iostream.h	1999/08/05 14:27:55
@@ -173,6 +173,7 @@
     int get() { if (!ipfx1()) return EOF;
 		else { int ch = _strbuf->sbumpc();
 		       if (ch == EOF) set(ios::eofbit);
+		       isfx();
 		       return ch;
 		     } }
     int peek();
Index: isgetline.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/isgetline.cc,v
retrieving revision 1.3
diff -u -a -r1.3 isgetline.cc
--- isgetline.cc	1998/04/19 21:14:32	1.3
+++ isgetline.cc	1999/08/05 14:27:55
@@ -37,6 +37,8 @@
   int ch;
   if (ipfx1())
     {
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				_strbuf);
       streambuf *sb = rdbuf();
       _gcount = _IO_getline_info(sb, buf, len - 1, delim, -1, &ch);
       if (ch != EOF)
@@ -48,6 +50,8 @@
 	  set(ios::failbit);
 	  sb->sungetc(); // Leave delimiter unread.
 	}
+      isfx();
+      _IO_cleanup_region_end (0);
     }
   else
     ch = EOF;
@@ -67,11 +71,15 @@
     }
   if (ipfx1())
     {
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				_strbuf);
       streambuf *sbuf = rdbuf();
       int ch;
       _gcount = _IO_getline_info(sbuf, buf, len - 1, delim, -1, &ch);
       if (_gcount == 0 && ch == EOF)
 	set(ios::failbit|ios::eofbit);
+      isfx();
+      _IO_cleanup_region_end (0);
     }
   buf[_gcount] = '\0';
   return *this;
@@ -123,6 +131,8 @@
 istream& istream::gets(char **s, char delim /* = '\n' */)
 {
     if (ipfx1()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	long size = 0;
 	streambuf *sb = rdbuf();
 	*s = _sb_readline (sb, size, delim);
@@ -132,6 +142,8 @@
 	    if (_gcount == 0)
 		set(ios::failbit);
 	}
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     else {
 	_gcount = 0;
Index: isgetsb.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/isgetsb.cc,v
retrieving revision 1.1.1.1
diff -u -a -r1.1.1.1 isgetsb.cc
--- isgetsb.cc	1997/08/21 22:58:19	1.1.1.1
+++ isgetsb.cc	1999/08/05 14:27:55
@@ -31,6 +31,8 @@
   _gcount = 0;
   if (ipfx1())
     {
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				_strbuf);
       register streambuf* isb = rdbuf();
       for (;;)
 	{
@@ -54,6 +56,8 @@
 	  if (delimp != NULL)
 	    break;
 	}
+      isfx();
+      _IO_cleanup_region_end (0);
     }
   return *this;
 }
Index: isscan.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/isscan.cc,v
retrieving revision 1.1.1.1
diff -u -a -r1.1.1.1 isscan.cc
--- isscan.cc	1997/08/21 22:58:19	1.1.1.1
+++ isscan.cc	1999/08/05 14:27:55
@@ -29,10 +29,14 @@
 istream& istream::scan(const char *format ...)
 {
     if (ipfx0()) {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	va_list ap;
 	va_start(ap, format);
 	_strbuf->vscan(format, ap, this);
 	va_end(ap);
+	isfx();
+	_IO_cleanup_region_end (0);
     }
     return *this;
 }
@@ -40,6 +44,12 @@
 istream& istream::vscan(const char *format, _IO_va_list args)
 {
     if (ipfx0())
+      {
+	_IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+				  _strbuf);
 	_strbuf->vscan(format, args, this);
+	isfx();
+	_IO_cleanup_region_end (0);
+      }
     return *this;
 }

-- 
Andreas Schwab                                  "And now for something
schwab@suse.de                                   completely different."
SuSE GmbH, Schanzäckerstr. 10, D-90443 Nürnberg

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