amd64/59650: sprintf() bus errors in non-main thread with %f
adriaan de groot
adridg at cs.kun.nl
Mon Nov 24 11:10:20 PST 2003
>Number: 59650
>Category: amd64
>Synopsis: sprintf() bus errors in non-main thread with %f
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-amd64
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Nov 24 11:10:17 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: adridg at cs.kun.nl
>Release: FreeBSD 5.1-CURRENT amd64
>Organization:
KDE-FreeBSD
>Environment:
System: FreeBSD beans.ebn.kun.nl 5.1-CURRENT FreeBSD 5.1-CURRENT #4: Wed Nov
19 14:11:35 CET 2003
root at beans.ebn.kun.nl:/mnt/sys/CURRENT/src/sys/amd64/compile/BEANS amd64
>Description:
The ogg123 port bus errors on an amd64 machine. This is because
sprintf() and fprintf() do "something weird" with %f arguments
in threads that are not the main thread of control.
>How-To-Repeat:
This program demonstrates the problem:
/* Demonstration program that shows that sprintf() doesn't
work with double args from threads that aren't the main
thread of control.
*/
#include <stdio.h>
#include <pthread.h>
#include <time.h>
void slipper(void *p)
{
fprintf(stderr,"[%lx] d=%d t=%d\n",(long)pthread_self(),3,time(NULL));
sleep(3);
fprintf(stderr,"%f\n",22/7);
fprintf(stderr,"%06.3f\n",0.002462390263402);
}
int main(int argc, char **argv)
{
pthread_t tid;
slipper(NULL);
pthread_create(&tid,NULL,slipper,NULL);
sleep(6);
slipper(NULL);
return 0;
}
}
Expected output is something like
[lofi at lofi]:0:~ > ./threadtest
[804c000] d=3 t=1069603991
0.000000
00.002
[804c400] d=3 t=1069603994
0.000000
00.002
[804c000] d=3 t=1069604000
0.000000
00.002
and on 4-STABLE i386, 5-CURRENT i386, and 5-CURRENT alpha,
that is exactly what it does. On amd64, however,
beans.ebn.kun.nl$./threadtest
[504000] d=3 t=1069604372
0.000000
00.002
[504800] d=3 t=1069604375
0.000000
Bus error (core dumped)
Note that the "plain" %f when printing a 0 value works,
but that sprintf() bus errors in the second call.
Replacing 22/7 by the constant 0.002462390263402 in the
code causes a bus error in the first call to sprintf().
(gdb) bt
#0 0x0000000200841189 in fprintf () from /lib/libc.so.5
#1 0x000000000040086f in slipper ()
#2 0x000000020063c670 in _thread_start () from /usr/lib/libc_r.so.5
Error accessing memory address 0x7fffffeff000: Bad address.
Possibly relevant disassembly:
0x0000000200841181 <fprintf+125>: movaps %xmm2,0xffffffffffffffa1(%rax)
0x0000000200841185 <fprintf+129>: movaps %xmm1,0xffffffffffffff91(%rax)
0x0000000200841189 <fprintf+133>: movaps %xmm0,0xffffffffffffff81(%rax)
0x000000020084118d <fprintf+137>: mov %rsi,0xffffffffffffff40(%rbp)
0x0000000200841194 <fprintf+144>: movl $0x10,0xffffffffffffff10(%rbp)
0x000000020084119e <fprintf+154>: movl $0x30,0xffffffffffffff14(%rbp)
(If it's gonna bus error, I'll suspect those odd constants in
the three movaps instructions.)
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-amd64
mailing list