Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Jan 2001 19:48:25 -0800
From:      Mike Smith <msmith@freebsd.org>
To:        Kevin Day <toasty@temphost.dragondata.com>
Cc:        hackers@freebsd.org, kevin@stileproject.com
Subject:   Re: Pthreads with sprintf/dtoa 
Message-ID:  <200101250348.f0P3mPI02756@mass.dis.org>
In-Reply-To: Your message of "Wed, 24 Jan 2001 18:29:58 CST." <200101250029.SAA23574@temphost.dragondata.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multipart MIME message.

--==_Exmh_-7024949920
Content-Type: text/plain; charset=us-ascii

> 
> 
> After upgrading to FreeBSD 4.2(from 4.1) and MySQL 3.23.32 (from 3.22.32), I
> kept seeing mysqld crashes after a few minutes of heavy load. I traced it
> down to one rather situation. Every time it crashed, I was getting a
> segfault inside __dtoa (which was called by sprintf). If I looked at other
> threads, I'd always see another thread inside __dtoa at that point too.
> 
> I went back to 3.22.32, and it still happened, so my current guess is
> something between 4.1-RELEASE and 4.2-RELEASE.
> 
> I'm really highly ignorant of pthreads, so I have no idea if they(myslqd) is
> doing something wrong thread-wise, or something got broken so that it's no
> longer thread safe inside sprintf or dtoa.
> 
> Can someone cluefull point me in the right direction? 

Sure.  

        static Bigint *result;
        static int result_k;

__dtoa has static locals.  Bad function, no biscuit.

I think that it does this in an attempt to avoid malloc thrash if it's 
called frequently; only resizing the result buffer if it actually needs a 
larger one.

Making this work "right" will be a bit ugly, since you'll need to fix 
__dtoa to always return a buffer allocated with malloc, and then teach 
vfprintf how to deal with a volatile string.  The handling of the result 
buffer in __dtoa is truly evil, and the author should most definitely 
have been shot.

Attached is an (untested) patch.  The sizing of the return buffer in 
__dtoa is a guess, based on trying to work out what the original code was 
doing, and may be off-by-one.




--==_Exmh_-7024949920
Content-Type: application/x-patch ; name="dtoa.patch"
Content-Description: dtoa.patch
Content-Disposition: attachment; filename="dtoa.patch"

Index: stdio/vfprintf.c
===================================================================
RCS file: /local0/src/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/25 03:25:28
@@ -287,6 +287,7 @@
 #define	SHORTINT	0x040		/* short integer */
 #define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
 #define FPT		0x100		/* Floating point number */
+#define	MUSTFREE	0x200		/* sp must be freed */
 int
 vfprintf(fp, fmt0, ap)
 	FILE *fp;
@@ -610,6 +611,7 @@
 			flags |= FPT;
 			cp = cvt(_double, prec, flags, &softsign,
 				&expt, ch, &ndig);
+			flags |= MUSTFREE;
 			if (ch == 'g' || ch == 'G') {
 				if (expt <= -4 || expt > prec)
 					ch = (ch == 'g') ? 'e' : 'E';
@@ -861,6 +863,10 @@
 		ret += prsize;
 
 		FLUSH();	/* copy out the I/O vectors */
+
+		/* free cp if it was allocated elsewhere */
+		if (flags & MUSTFREE)
+			free(cp);
 	}
 done:
 	FLUSH();
Index: stdlib/strtod.c
===================================================================
RCS file: /local0/src/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	2001/01/25 03:43:08
@@ -1890,16 +1890,7 @@
 	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
 	double d2, ds, eps;
 	char *s, *s0;
-	static Bigint *result;
-	static int result_k;
-
-	if (result) {
-		result->k = result_k;
-		result->maxwds = 1 << result_k;
-		Bfree(result);
-		result = 0;
-	}
-
+	
 	if (word0(d) & Sign_bit) {
 		/* set sign for everything, including 0's and NaNs */
 		*sign = 1;
@@ -1917,11 +1908,11 @@
 	{
 		/* Infinity or NaN */
 		*decpt = 9999;
-		s =
+		s = strdup(
 #ifdef IEEE_Arith
 			!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
 #endif
-				"NaN";
+				"NaN");
 		if (rve)
 			*rve =
 #ifdef IEEE_Arith
@@ -1936,7 +1927,7 @@
 #endif
 	if (!d) {
 		*decpt = 1;
-		s = "0";
+		s = strdup("0");
 		if (rve)
 			*rve = s + 1;
 		return s;
@@ -2057,11 +2048,10 @@
 			if (i <= 0)
 				i = 1;
 	}
-	j = sizeof(unsigned long);
-	for (result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i;
-		j <<= 1) result_k++;
-	result = Balloc(result_k);
-	s = s0 = (char *)result;
+	/* XXX verify that i is always large enough?  Add padding? */
+	s = s0 = malloc(i);
+	if (s0 == NULL)
+		return s0;
 
 	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
 

--==_Exmh_-7024949920
Content-Type: text/plain; charset=us-ascii

... every activity meets with opposition, everyone who acts has his
rivals and unfortunately opponents also.  But not because people want
to be opponents, rather because the tasks and relationships force
people to take different points of view.  [Dr. Fritz Todt]
           V I C T O R Y   N O T   V E N G E A N C E

--==_Exmh_-7024949920--




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




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