This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libgcj/8027: SharedLibLoader is prematurely finalized, causing a core dump


>Number:         8027
>Category:       libgcj
>Synopsis:       SharedLibLoader is prematurely finalized, causing a core dump
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 24 19:26:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     jsturm@one-point.com
>Release:        gcc version 3.3 20020906 (experimental)
>Organization:
>Environment:
Reading specs from /opt/gcc/lib/gcc-lib/alphaev56-unknown-linux-gnu/3.3/specs
Reading specs from /opt/gcc/lib/gcc-lib/alphaev56-unknown-linux-gnu/3.3/../../../libgcj.spec
rename spec lib to liborig
Configured with: /home/jsturm/gcc/configure --prefix=/opt/gcc --enable-threads --with-as=/opt/src/bin/as --with-ld=/opt/src/bin/ld
Thread model: posix
>Description:
The attached program dumps core when the SharedLibLoader is finalized.  There are several things happening here:

a) Class B incorrectly displays VMClassLoader, when it is loaded by SharedLibLoader.

b) Classes loaded by SharedLibLoader don't preserve a reference to their class loader, so the loader is GC'ed and finalized while B is still live.

c) Hans Boehm points out that dlclose()ing the library is unsafe regardless of whether any live class objects exist:

http://gcc.gnu.org/ml/java/2002-09/msg00211.html

d) The test program may not simply terminate on a java exception, since the pc is invalid and unwind info gone after dlclose.
>How-To-Repeat:
$ cat A.java
import gnu.gcj.runtime.SharedLibLoader;

public class A {
  public static Class getB() throws ClassNotFoundException {
    return (new SharedLibLoader("libB.so")).loadClass("B");
  }

  public static void main(String[] args) throws ClassNotFoundException {
    Class bClass = getB();

    for (int n = 0; n < 10000; n++)
      try {
	((Runnable)bClass.newInstance()).run();
      } catch (Throwable t) {
	t.printStackTrace();
      }
  }
}

$ cat B.java
public class B implements Runnable {
  public void run() {
    System.out.println(getClass().getClassLoader());
  }
}

$ gcj -shared B.java -o natB.so
$ gcj A.java --main=A -o A
$ env LD_LIBRARY_PATH=`pwd` GC_PRINT_STATS=1 ./A
...gnu.gcj.runtime.VMClassLoader@200cff92
gnu.gcj.runtime.VMClassLoader@200cff92
gnu.gcj.runtime.VMClassLoader@200cff92
Initiating full world-stop collection 2 after 2015640 allocd bytes
--> Marking for collection 2 after 2015640 allocd bytes + 12264 wasted bytes
Collection 1 finished ---> heapsize = 2301952 bytes
World-stopped marking took 16 msecs
gnu.gcj.runtime.VMClassLoader@200cff92
Segmentation fault (core dumped)

>Fix:
Set the "loader" field of the loaded classes to its SharedLibLoader.  Unfortunately, that makes SharedLibLoader somewhat useless in that it can no longer be unloaded.  The "right" fix is not so obvious.
>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]