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>
