Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Jan 2001 18:40:06 -0800 (PST)
From:      Tor.Egge@fast.no
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/15070: vfprintf/cvt/__dtoa race condition in threaded programs
Message-ID:  <200101150240.f0F2e6w52001@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

The following reply was made to PR bin/15070; it has been noted by GNATS.

From: Tor.Egge@fast.no
To: freebsd-gnats-submit@FreeBSD.ORG
Cc:  
Subject: Re: bin/15070: vfprintf/cvt/__dtoa race condition in threaded programs
Date: Mon, 15 Jan 2001 03:35:04 +0100

 One workaround for the race is to serialize vfprintf() calls that use
 floating point conversion specifications.
 
 
 Index: stdio/vfprintf.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/vfprintf.c,v
 retrieving revision 1.23
 diff -u -r1.23 vfprintf.c
 --- stdio/vfprintf.c	2001/01/06 20:48:00	1.23
 +++ stdio/vfprintf.c	2001/01/06 23:15:45
 @@ -261,6 +261,17 @@
  #include <math.h>
  #include "floatio.h"
  
 +/* 
 + * Serialize calls to cvt and __dtoa() and the usage of the result
 + * in threaded programs.
 + */
 +
 +#include "libc_private.h"
 +#include "spinlock.h"
 +static spinlock_t thread_lock	= _SPINLOCK_INITIALIZER;
 +#define THREAD_LOCK()		if (__isthreaded) _SPINLOCK(&thread_lock);
 +#define THREAD_UNLOCK()		if (__isthreaded) _SPINUNLOCK(&thread_lock);
 +
  #define	BUF		(MAXEXP+MAXFRACT+1)	/* + decimal point */
  #define	DEFPREC		6
  
 @@ -271,6 +282,9 @@
  
  #define	BUF		68
  
 +#define THREAD_LOCK()
 +#define THREAD_UNLOCK()
 +
  #endif /* FLOATING_POINT */
  
  #define STATIC_ARG_TBL_SIZE 8           /* Size of static argument table. */
 @@ -303,6 +317,7 @@
  	int width;		/* width from format (%8d), or 0 */
  	int prec;		/* precision from format (%.3d), or -1 */
  	char sign;		/* sign prefix (' ', '+', '-', or \0) */
 +	int didlock;		/* have obtained thread lock */
  #ifdef FLOATING_POINT
  	char softsign;		/* temporary negative sign for floats */
  	double _double;		/* double precision arguments %[eEfgG] */
 @@ -418,6 +433,7 @@
          }
          
  
 +	didlock = 0;
  	FLOCKFILE(fp);
  	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
  	if (cantwrite(fp)) {
 @@ -608,6 +624,8 @@
  				break;
  			}
  			flags |= FPT;
 +			THREAD_LOCK();
 +			didlock = 1;
  			cp = cvt(_double, prec, flags, &softsign,
  				&expt, ch, &ndig);
  			if (ch == 'g' || ch == 'G') {
 @@ -849,6 +867,10 @@
  					PRINT(cp, 1);
  				PRINT(expstr, expsize);
  			}
 +			if (didlock != 0) {
 +			  THREAD_UNLOCK();
 +			  didlock = 0;
 +			}
  		}
  #else
  		PRINT(cp, size);
 @@ -865,6 +887,10 @@
  done:
  	FLUSH();
  error:
 +	if (didlock != 0) {
 +	  THREAD_UNLOCK();
 +	  didlock = 0;
 +	}
  	if (__sferror(fp))
  		ret = EOF;
  	FUNLOCKFILE(fp);
 Index: stdlib/strtod.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdlib/strtod.c,v
 retrieving revision 1.3
 diff -u -r1.3 strtod.c
 --- stdlib/strtod.c	1996/07/12 18:55:22	1.3
 +++ stdlib/strtod.c	2000/06/15 03:48:29
 @@ -371,6 +371,16 @@
  
   static Bigint *freelist[Kmax+1];
  
 +  /*
 +   * Make Balloc/Bfree thread-safe in libc for use with
 +   * kernel threads.
 +   */
 +#include "libc_private.h"
 +#include "spinlock.h"
 +static spinlock_t thread_lock	= _SPINLOCK_INITIALIZER;
 +#define THREAD_LOCK()		if (__isthreaded) _SPINLOCK(&thread_lock);
 +#define THREAD_UNLOCK()		if (__isthreaded) _SPINUNLOCK(&thread_lock);
 +
   static Bigint *
  Balloc
  #ifdef KR_headers
 @@ -382,9 +392,12 @@
  	int x;
  	Bigint *rv;
  
 +	THREAD_LOCK();
  	if ( (rv = freelist[k]) ) {
  		freelist[k] = rv->next;
 +		THREAD_UNLOCK();
  	} else {
 +		THREAD_UNLOCK();
  		x = 1 << k;
  		rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long));
  		rv->k = k;
 @@ -403,8 +416,10 @@
  #endif
  {
  	if (v) {
 +		THREAD_LOCK();
  		v->next = freelist[v->k];
  		freelist[v->k] = v;
 +		THREAD_UNLOCK();
  	}
  }
  
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101150240.f0F2e6w52001>