|
Evaluation
|
The problem is caused by a bug in /lib/libc.so library.
RedHat6.2 uses version 2.1.2 of the library
RedHat7.0 uses version 2.2 of the library.
libc's function exit() was changed dramatically. I don't have the library sources but I studied disassembly of the both libraries. It looks like exit()
in 2.2 does not save exit status code, when invokes handlers registered with atexit() call. See for yourself.
libc-2.1.2::exit()
--------------------
00020970 <exit>:
20970: 55 pushl %ebp
20971: 89 e5 movl %esp,%ebp
20973: 57 pushl %edi
20974: 56 pushl %esi
20975: 53 pushl %ebx
20976: e8 00 00 00 00 call 2097b <exit+0xb>
2097b: 5b popl %ebx
2097c: 81 c3 11 db 0c 00 addl $0xcdb11,%ebx
20982: 8b 8b b8 07 00 00 movl 0x7b8(%ebx),%ecx
20988: 83 39 00 cmpl $0x0,(%ecx)
2098b: 0f 84 7d 00 00 00 je 20a0e <exit+0x9e>
20991: 8b 01 movl (%ecx),%eax
20993: 8b 50 04 movl 0x4(%eax),%edx
20996: 8d 7a ff leal 0xffffffff(%edx),%edi
20999: 89 78 04 movl %edi,0x4(%eax)
2099c: 8d 54 52 fd leal 0xfffffffd(%edx,%edx,2),%edx
209a0: 8b 01 movl (%ecx),%eax
209a2: 8d 54 90 08 leal 0x8(%eax,%edx,4),%edx
209a6: 8b 02 movl (%edx),%eax
209a8: 83 f8 03 cmpl $0x3,%eax
209ab: 77 39 ja 209e6 <exit+0x76>
209ad: 89 df movl %ebx,%edi
209af: 2b bc 83 34 25 f3 ff subl 0xfff32534(%ebx,%eax,4),%edi
209b6: ff e7 jmp *%edi
209b8: 90 nop
209b9: 8d b4 26 00 00 00 00 leal 0x0(%esi,1),%esi
209c0: a6 cmpsb %ds:(%esi),%es:(%edi)
209c1: da 0c 00 fimull (%eax,%eax,1)
209c4: a6 cmpsb %ds:(%esi),%es:(%edi)
209c5: da 0c 00 fimull (%eax,%eax,1)
209c8: bc da 0c 00 ab movl $0xab000cda,%esp
209cd: da 0c 00 fimull (%eax,%eax,1)
209d0: ff 72 08 pushl 0x8(%edx)
209d3: 8b 7d 08 movl 0x8(%ebp),%edi
209d6: 57 pushl %edi
209d7: 8b 42 04 movl 0x4(%edx),%eax
209da: ff d0 call *%eax
209dc: 83 c4 08 addl $0x8,%esp
209df: eb 05 jmp 209e6 <exit+0x76>
209e1: 8b 42 04 movl 0x4(%edx),%eax
209e4: ff d0 call *%eax
209e6: 8b 8b b8 07 00 00 movl 0x7b8(%ebx),%ecx
209ec: 8b 11 movl (%ecx),%edx
209ee: 83 7a 04 00 cmpl $0x0,0x4(%edx)
209f2: 75 9d jne 20991 <exit+0x21>
209f4: 8b 02 movl (%edx),%eax
209f6: 89 01 movl %eax,(%ecx)
209f8: 52 pushl %edx
209f9: e8 4e 74 ff ff call 17e4c <GLIBC_2.0+0x17e4c>
209fe: 83 c4 04 addl $0x4,%esp
20a01: 8b 83 b8 07 00 00 movl 0x7b8(%ebx),%eax
20a07: 89 c1 movl %eax,%ecx
20a09: 83 39 00 cmpl $0x0,(%ecx)
20a0c: 75 83 jne 20991 <exit+0x21>
20a0e: 8b b3 bc 07 00 00 movl 0x7bc(%ebx),%esi
20a14: 3b b3 c0 07 00 00 cmpl 0x7c0(%ebx),%esi
20a1a: 73 13 jae 20a2f <exit+0xbf>
20a1c: 8d 74 26 00 leal 0x0(%esi,1),%esi
20a20: 8b 06 movl (%esi),%eax
20a22: ff d0 call *%eax
20a24: 83 c6 04 addl $0x4,%esi
20a27: 3b b3 c0 07 00 00 cmpl 0x7c0(%ebx),%esi
20a2d: 72 f1 jb 20a20 <exit+0xb0>
20a2f: 8b 7d 08 movl 0x8(%ebp),%edi
20a32: 57 pushl %edi
20a33: e8 64 71 ff ff call 17b9c <GLIBC_2.0+0x17b9c>
20a38: 90 nop
20a39: 90 nop
libc-2.2::exit()
----------------
0002f744 <exit>:
2f744: 55 push %ebp
2f745: 89 e5 mov %esp,%ebp
2f747: 57 push %edi
2f748: 56 push %esi
2f749: 53 push %ebx
2f74a: 83 ec 0c sub $0xc,%esp
2f74d: e8 ee ff ff ff call 2f740 <__secure_getenv+0x4c>
2f752: 81 c3 76 61 0f 00 add $0xf6176,%ebx
2f758: 8b b3 dc 07 00 00 mov 0x7dc(%ebx),%esi
2f75e: 8b 7d 08 mov 0x8(%ebp),%edi
2f761: 8b 16 mov (%esi),%edx
2f763: 85 d2 test %edx,%edx
2f765: 0f 84 9b 00 00 00 je 2f806 <exit+0xc2>
2f76b: 90 nop
2f76c: 8d 74 26 00 lea 0x0(%esi,1),%esi
2f770: 8b 06 mov (%esi),%eax
2f772: 89 f2 mov %esi,%edx
2f774: 8b 40 04 mov 0x4(%eax),%eax
2f777: 85 c0 test %eax,%eax
2f779: 74 64 je 2f7df <exit+0x9b>
2f77b: 90 nop
2f77c: 8d 74 26 00 lea 0x0(%esi,1),%esi
2f780: 8b 12 mov (%edx),%edx
2f782: 8b 42 04 mov 0x4(%edx),%eax
2f785: 48 dec %eax
2f786: 89 42 04 mov %eax,0x4(%edx)
2f789: c1 e0 04 shl $0x4,%eax
2f78c: 01 c2 add %eax,%edx
2f78e: 8b 42 08 mov 0x8(%edx),%eax
2f791: 8d 4a 08 lea 0x8(%edx),%ecx
2f794: 83 f8 04 cmp $0x4,%eax
2f797: 77 35 ja 2f7ce <exit+0x8a>
2f799: 8b b4 83 e0 9e f0 ff mov 0xfff09ee0(%ebx,%eax,4),%esi
2f7a0: 89 da mov %ebx,%edx
2f7a2: 29 f2 sub %esi,%edx
2f7a4: 89 d0 mov %edx,%eax
2f7a6: ff e0 jmp *%eax
2f7a8: fa cli
2f7a9: 60 pusha
2f7aa: 0f 00 (bad)
2f7ac: fa cli
2f7ad: 60 pusha
2f7ae: 0f 00 08 str (%eax)
2f7b1: 61 popa
2f7b2: 0f 00 98 60 0f 00 93 ltr 0x93000f60(%eax)
2f7b9: 60 pusha
2f7ba: 0f 00 8d 74 26 00 8b str 0x8b002674(%ebp)
2f7c1: 41 inc %ecx
2f7c2: 08 83 ec 08 50 57 or %al,0x575008ec(%ebx)
2f7c8: ff 51 04 call *0x4(%ecx)
2f7cb: 83 c4 10 add $0x10,%esp
2f7ce: 8b b3 dc 07 00 00 mov 0x7dc(%ebx),%esi
2f7d4: 8b 06 mov (%esi),%eax
2f7d6: 89 f2 mov %esi,%edx
2f7d8: 8b 48 04 mov 0x4(%eax),%ecx
2f7db: 85 c9 test %ecx,%ecx
2f7dd: 75 a1 jne 2f780 <exit+0x3c>
2f7df: 8b 16 mov (%esi),%edx
2f7e1: 8b 02 mov (%edx),%eax
2f7e3: 85 c0 test %eax,%eax
2f7e5: 89 06 mov %eax,(%esi)
2f7e7: 74 0c je 2f7f5 <exit+0xb1>
2f7e9: 83 ec 0c sub $0xc,%esp
2f7ec: 52 push %edx
2f7ed: e8 56 c4 fe ff call 1bc48 <GLIBC_2.0+0x1bc48>
2f7f2: 83 c4 10 add $0x10,%esp
2f7f5: 8b 06 mov (%esi),%eax
2f7f7: 85 c0 test %eax,%eax
2f7f9: 74 0b je 2f806 <exit+0xc2>
2f7fb: 8b b3 dc 07 00 00 mov 0x7dc(%ebx),%esi
2f801: e9 6a ff ff ff jmp 2f770 <exit+0x2c>
2f806: 8b b3 bc 08 00 00 mov 0x8bc(%ebx),%esi
2f80c: 3b b3 3c 09 00 00 cmp 0x93c(%ebx),%esi
2f812: 73 2c jae 2f840 <exit+0xfc>
2f814: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
2f81a: 8d bf 00 00 00 00 lea 0x0(%edi),%edi
2f820: ff 16 call *(%esi)
2f822: 83 c6 04 add $0x4,%esi
2f825: 3b b3 3c 09 00 00 cmp 0x93c(%ebx),%esi
2f82b: 72 f3 jb 2f820 <exit+0xdc>
2f82d: eb 11 jmp 2f840 <exit+0xfc>
2f82f: 90 nop
2f830: ff 51 04 call *0x4(%ecx)
2f833: eb 99 jmp 2f7ce <exit+0x8a>
2f835: 8b 71 08 mov 0x8(%ecx),%esi
2f838: 83 ec 0c sub $0xc,%esp
2f83b: 56 push %esi
2f83c: eb 8a jmp 2f7c8 <exit+0x84>
2f83e: 89 f6 mov %esi,%esi
2f840: 83 ec 0c sub $0xc,%esp
2f843: 57 push %edi
2f844: e8 5f c1 fe ff call 1b9a8 <GLIBC_2.0+0x1b9a8>
2f849: 90 nop
2f84a: 90 nop
2f84b: 90 nop
2f84c: 90 nop
2f84d: 90 nop
2f84e: 90 nop
2f84f: 90 nop
2f850: 8b 1c 24 mov (%esp,1),%ebx
2f853: c3 ret
xxxxx@xxxxx 2000-12-20
I inserted printouts in os::exit() and VM_Exit::doit() to make sure that exit status code is passed correctly to libc::exit(). results look as follows:
s/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=80da240 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=80d9628 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=80d9628 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=80d8a20 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=80d8a20 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=80d0e18 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=80d0e18 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=80cf7a0 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=80cf7a0 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=805f610 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:695
exit _code=55 thread=805f610 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:697
exit _code=55 thread=805f610 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:701
exit _code=55 thread=805f610 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:703
exit _code=55 thread=805f610 at/.automount/jano/root/export/disk07/runtime/users/wdavid/1.4_sa/build/linux/../../src/os/linux/vm/os_linux.cpp:708
No doubts the bug is in the library.
The bug only shows up when atexit handlers are invoked.
xxxxx@xxxxx 2000-12-20
The bug is actually is the libpthread-0.9 that comes with glibc-2.2
The new libpthread attachs the exit handler with cxa_atexit() instead
of on_exit() (the cxa_handler is supposed to be called also when the
shared library is unloaded). But the cxa exit handler flavor is not called
with the exit code during exit(). The cxa handler takes only one argument
specified when cxa_atexit() is called. The new libpthread sets this
argument to NULL and by side effect this argument becomes the exit code of
the process.
Note that this is only a problem if the thread that does exit() is not the main
thread.
Potential workaround in the JVM: force the main thread to do the exit().
xxxxx@xxxxx 2001-01-10
I had a meeting with Ludo and we dicussed the bug. It is not only Hotspot problem, any multythread application is affected. The bug in pthread library caused wrong exit code was filed with RedHat. The bug and lot of xxxxx libc bugs are expected to be fixed in RedHat 7.1. So we propose upgrade to 7.1 as
a "workaround" for this bug.
RedHat bug Id: 23758
location: http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=23758
xxxxx@xxxxx 2001-02-06
|
|
Comments
|
Submitted On 19-NOV-2000
KleemannR
Apparently, this also affects the return value of javac
which makes it impossible to build java projects with
makefiles. A workaround until this bug is fixed is to use
IBM's java 1.3 sdk.
Submitted On 21-NOV-2000
cjs@cynic.net
The javac return value problem was how I found the bug in
the first place, in fact. I have a script that finds all of
the outdated files in my tree and runs a single javac to
build them all (this is much faster than invoking javac
individually for each out-of-date files). My workaround was
to add code to this script to check again after compilation
for out-of-date files and exit with an error value should
any still exist. You could do the same with your .java.class
rules in your Makefile.
Submitted On 11-DEC-2000
gregholt
Please note that my above workaround does nothing for Java
programs that call System.exit. This only really helps when
compiling projects using Makefiles. It also has the side
effect of always returning exit code 1 if any data is output
to stderr.
Greg Holt
Submitted On 11-DEC-2000
gregholt
I had posted this on bug 4383241, which was closed without
full and proper testing...
This is very reproducible on RedHat Linux 7.0, with or
without all known updates from updates.redhat.com.
[greg@opal greg]$ cat z.java
class z {
final int foo;
}
[greg@opal greg]$ javac z.java; echo exit value: $?
z.java:1: variable foo might not have been initialized
class z {
^
1 error
exit value: 0
[greg@opal greg]$ uname -a
Linux opal.inner.brim.net 2.2.16-22 #1 Tue Aug 22 16:49:06
EDT 2000 i686 unknown
[greg@opal greg]$ java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build
1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)
If you edit /usr/java/jdk1.3/bin/.java_wrapper and change
the line:
exec $DEBUG_PROG "$prog" "$@"
to:
$DEBUG_PROG "$prog" "$@"; echo .java_wrapper exit code: $?
and run the same test, you get:
[greg@opal greg]$ javac z.java
z.java:1: variable foo might not have been initialized
class z {
^
1 error
.java_wrapper exit code: 0
Which indicates that it is *not* a problem with
.java_wrapper itself, but the executable being called. In my
case this is
"/usr/java/jdk1.3/bin/i386/native_threads/javac".
Workaround (very kludgy!):
Modify /usr/java/jdk1.3/bin/.java_wrapper:
Change the line that reads:
exec $DEBUG_PROG "$prog" "$@"
to:
tmpfile="/tmp/java_${UID}_${PPID}_${SECONDS}_${RANDOM}.tmp"
$DEBUG_PROG "$prog" "$@" 2> $tmpfile
if [ -s $tmpfile ]; then
cat $tmpfile
rm $tmpfile
exit 1
fi
rm $tmpfile
Then, the test performs correctly:
[greg@opal greg]$ javac z.java; echo exit value: $?
z.java:1: variable foo might not have been initialized
class z {
^
1 error
exit value: 1
HOWEVER: This has the side-effect of buffering all stderr
output and only dumping it at the end, which may affect how
valid programs run with "java" work that use System.err.*.
It does keep my Makefiles informed of compilation errors
though and saves me a ton of headscratching when a program I
*thought* built fine didn't.
Greg Holt
Submitted On 13-DEC-2000
egoine
Please fix this! It's breaking so much stuff!
Submitted On 15-DEC-2000
cjs@cynic.net
Is someone from Sun actually dealing with this? It's a
pretty major problem that one would think would not be
rocket science to fix, and it's been over a month now.
Submitted On 21-DEC-2000
gregholt
Has this been reported to Red Hat? Does this mean we should
just use IBM's JDK until "someone" fixes this?
Submitted On 10-JAN-2001
Bill_CCHKK
A quick note. It was reported that this fails on RedHat 7
but works on RedHat 6.2. RedHat 7 uses glibc version
2.1.92, and was updated to 2.1.94 and then to 2.2. I'm
running with the 2.1.94 version, and it is broke there as
well.
However, if I run the 1.2.2 JDK from blackdown (based on the
Sun code) on Red Hat 7, the behavior is correct, the return
code is correct.
Submitted On 12-JAN-2001
Bill_CCHKK
FYI, everyone, it looks like someone (presumably xxxxx@xxxxx
abover :-) ) reported this bug to Redhat. Take a look at
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=23758
for the details.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|