aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortromey <>2006-01-06 01:03:45 +0000
committertromey <>2006-01-06 01:03:45 +0000
commit86f7728d8a4f33a3c9e01c5d85b2ba2d17315391 (patch)
treeb1406d0aef45f9b54fc3cb3b56375bc3ce39b15c
parentd3952cb241cc5deac4e5c01208a89f85de612826 (diff)
* java/lang/natThread.cc (finish_): Don't clear 'group'.
* sources.am, Makefile.in: Rebuilt. * java/lang/Runtime.java (exit): Merged with Classpath. (runShutdownHooks): New method from Classpath. * java/io/File.java (deleteOnExit): Use DeleteFileHelper, not FileDeleter. * gnu/gcj/runtime/FileDeleter.java: Removed. * java/lang/natRuntime.cc (runFinalizationForExit): New method. (exitInternal): Don't run finalizers or delete files.
-rw-r--r--libjava/ChangeLog12
-rw-r--r--libjava/Makefile.in1
-rw-r--r--libjava/gnu/gcj/runtime/FileDeleter.java35
-rw-r--r--libjava/gnu/java/lang/natMainThread.cc16
-rw-r--r--libjava/java/io/File.java5
-rw-r--r--libjava/java/lang/Runtime.java120
-rw-r--r--libjava/java/lang/natRuntime.cc16
-rw-r--r--libjava/java/lang/natThread.cc4
-rw-r--r--libjava/prims.cc8
-rw-r--r--libjava/sources.am1
10 files changed, 122 insertions, 96 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index a2cc01e4ad7..4cbb9e738dd 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,5 +1,17 @@
2006-01-05 Tom Tromey <tromey@redhat.com>
+ * java/lang/natThread.cc (finish_): Don't clear 'group'.
+ * sources.am, Makefile.in: Rebuilt.
+ * java/lang/Runtime.java (exit): Merged with Classpath.
+ (runShutdownHooks): New method from Classpath.
+ * java/io/File.java (deleteOnExit): Use DeleteFileHelper, not
+ FileDeleter.
+ * gnu/gcj/runtime/FileDeleter.java: Removed.
+ * java/lang/natRuntime.cc (runFinalizationForExit): New method.
+ (exitInternal): Don't run finalizers or delete files.
+
+2006-01-05 Tom Tromey <tromey@redhat.com>
+
* java/lang/natPosixProcess.cc (reap): Ignore unknown children.
2006-01-04 Krister Walfridsson <cato@df.lth.se>
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index cec8b3875a8..66e5fc5c3c7 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -1168,7 +1168,6 @@ gnu_gcj_io_header_files = $(patsubst %.java,%.h,$(gnu_gcj_io_source_files))
gnu_gcj_runtime_source_files = \
gnu/gcj/runtime/BootClassLoader.java \
gnu/gcj/runtime/ExtensionClassLoader.java \
-gnu/gcj/runtime/FileDeleter.java \
gnu/gcj/runtime/FinalizerThread.java \
gnu/gcj/runtime/HelperClassLoader.java \
gnu/gcj/runtime/JNIWeakRef.java \
diff --git a/libjava/gnu/gcj/runtime/FileDeleter.java b/libjava/gnu/gcj/runtime/FileDeleter.java
deleted file mode 100644
index d5f99d04c47..00000000000
--- a/libjava/gnu/gcj/runtime/FileDeleter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2000 Free Software Foundation
-
- This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
-details. */
-
-package gnu.gcj.runtime;
-
-import java.io.*;
-import java.util.*;
-
-public final class FileDeleter
-{
- public synchronized static void add (File f)
- {
- if (deleteOnExitStack == null)
- deleteOnExitStack = new Stack ();
-
- deleteOnExitStack.push (f);
- }
-
- // Helper method called by java.lang.Runtime.exit() to perform
- // pending deletions.
- public synchronized static void deleteOnExitNow ()
- {
- if (deleteOnExitStack != null)
- while (!deleteOnExitStack.empty ())
- ((File)(deleteOnExitStack.pop ())).delete ();
- }
-
- // A stack of files to delete upon normal termination.
- private static Stack deleteOnExitStack;
-}
diff --git a/libjava/gnu/java/lang/natMainThread.cc b/libjava/gnu/java/lang/natMainThread.cc
index 7e8e4223dfe..95626eb3a71 100644
--- a/libjava/gnu/java/lang/natMainThread.cc
+++ b/libjava/gnu/java/lang/natMainThread.cc
@@ -1,6 +1,6 @@
// natMainThread.cc - Implementation of MainThread native methods.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2006 Free Software Foundation
This file is part of libgcj.
@@ -15,8 +15,11 @@ details. */
#include <gcj/cni.h>
#include <jvm.h>
+#include <java-threads.h>
#include <gnu/java/lang/MainThread.h>
+#include <java/lang/Runtime.h>
+#include <java/lang/ThreadGroup.h>
typedef void main_func (jobject);
@@ -45,4 +48,15 @@ gnu::java::lang::MainThread::call_main (void)
main_func *real_main = (main_func *) meth->ncode;
(*real_main) (args);
+
+ // Note that we do thread cleanup here. We have to do this here and
+ // not in _Jv_RunMain; if we do if after the main thread has exited,
+ // our ThreadGroup will be null, and if Runtime.exit tries to create
+ // a new Thread (which it does when running shutdown hooks), it will
+ // eventually NPE due to this.
+ _Jv_ThreadWait ();
+
+ int status = (int) ::java::lang::ThreadGroup::had_uncaught_exception;
+ ::java::lang::Runtime *runtime = ::java::lang::Runtime::getRuntime ();
+ runtime->exit (status);
}
diff --git a/libjava/java/io/File.java b/libjava/java/io/File.java
index e3d59cb7d24..1b02b601aaf 100644
--- a/libjava/java/io/File.java
+++ b/libjava/java/io/File.java
@@ -1,5 +1,5 @@
/* File.java -- Class representing a file on disk
- Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -44,7 +44,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import gnu.classpath.Configuration;
-import gnu.gcj.runtime.FileDeleter;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
@@ -1375,7 +1374,7 @@ public class File implements Serializable, Comparable
if (sm != null)
sm.checkDelete (getName());
- FileDeleter.add (this);
+ DeleteFileHelper.add(this);
}
private void writeObject(ObjectOutputStream oos) throws IOException
diff --git a/libjava/java/lang/Runtime.java b/libjava/java/lang/Runtime.java
index a30a44b2c22..519b4ac8c5e 100644
--- a/libjava/java/lang/Runtime.java
+++ b/libjava/java/lang/Runtime.java
@@ -1,5 +1,5 @@
/* Runtime.java -- access to the VM process
- Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation
+ Copyright (C) 1998, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -146,6 +146,56 @@ public class Runtime
SecurityManager sm = SecurityManager.current; // Be thread-safe!
if (sm != null)
sm.checkExit(status);
+
+ if (runShutdownHooks())
+ halt(status);
+
+ // Someone else already called runShutdownHooks().
+ // Make sure we are not/no longer in the shutdownHooks set.
+ // And wait till the thread that is calling runShutdownHooks() finishes.
+ synchronized (libpath)
+ {
+ if (shutdownHooks != null)
+ {
+ shutdownHooks.remove(Thread.currentThread());
+ // Interrupt the exit sequence thread, in case it was waiting
+ // inside a join on our thread.
+ exitSequence.interrupt();
+ // Shutdown hooks are still running, so we clear status to
+ // make sure we don't halt.
+ status = 0;
+ }
+ }
+
+ // If exit() is called again after the shutdown hooks have run, but
+ // while finalization for exit is going on and the status is non-zero
+ // we halt immediately.
+ if (status != 0)
+ halt(status);
+
+ while (true)
+ try
+ {
+ exitSequence.join();
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore, we've suspended indefinitely to let all shutdown
+ // hooks complete, and to let any non-zero exits through, because
+ // this is a duplicate call to exit(0).
+ }
+ }
+
+ /**
+ * On first invocation, run all the shutdown hooks and return true.
+ * Any subsequent invocations will simply return false.
+ * Note that it is package accessible so that VMRuntime can call it
+ * when VM exit is not triggered by a call to Runtime.exit().
+ *
+ * @return was the current thread the first one to call this method?
+ */
+ boolean runShutdownHooks()
+ {
boolean first = false;
synchronized (libpath) // Synch on libpath, not this, to avoid deadlock.
{
@@ -177,7 +227,7 @@ public class Runtime
// itself from the set, then waits indefinitely on the
// exitSequence thread. Once the set is empty, set it to null to
// signal all finalizer threads that halt may be called.
- while (! shutdownHooks.isEmpty())
+ while (true)
{
Thread[] hooks;
synchronized (libpath)
@@ -185,19 +235,27 @@ public class Runtime
hooks = new Thread[shutdownHooks.size()];
shutdownHooks.toArray(hooks);
}
- for (int i = hooks.length; --i >= 0; )
- if (! hooks[i].isAlive())
- synchronized (libpath)
+ if (hooks.length == 0)
+ break;
+ for (int i = 0; i < hooks.length; i++)
+ {
+ try
{
- shutdownHooks.remove(hooks[i]);
+ synchronized (libpath)
+ {
+ if (!shutdownHooks.contains(hooks[i]))
+ continue;
+ }
+ hooks[i].join();
+ synchronized (libpath)
+ {
+ shutdownHooks.remove(hooks[i]);
+ }
+ }
+ catch (InterruptedException x)
+ {
+ // continue waiting on the next thread
}
- try
- {
- Thread.sleep(1); // Give other threads a chance.
- }
- catch (InterruptedException e)
- {
- // Ignore, the next loop just starts sooner.
}
}
synchronized (libpath)
@@ -205,34 +263,11 @@ public class Runtime
shutdownHooks = null;
}
}
- // XXX Right now, it is the VM that knows whether runFinalizersOnExit
- // is true; so the VM must look at exitSequence to decide whether
- // this should be run on every object.
- runFinalization();
+ // Run finalization on all finalizable objects (even if they are
+ // still reachable).
+ runFinalizationForExit();
}
- else
- synchronized (libpath)
- {
- if (shutdownHooks != null)
- {
- shutdownHooks.remove(Thread.currentThread());
- status = 0; // Change status to enter indefinite wait.
- }
- }
-
- if (first || status > 0)
- halt(status);
- while (true)
- try
- {
- exitSequence.join();
- }
- catch (InterruptedException e)
- {
- // Ignore, we've suspended indefinitely to let all shutdown
- // hooks complete, and to let any non-zero exits through, because
- // this is a duplicate call to exit(0).
- }
+ return first;
}
/**
@@ -668,6 +703,11 @@ public class Runtime
private static native void init ();
/**
+ * Run finalizers when exiting.
+ */
+ private native void runFinalizationForExit();
+
+ /**
* Map a system-independent "short name" to the full file name, and append
* it to the path.
* XXX This method is being replaced by System.mapLibraryName.
diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc
index 300dc573247..5cca1b072a3 100644
--- a/libjava/java/lang/natRuntime.cc
+++ b/libjava/java/lang/natRuntime.cc
@@ -1,6 +1,6 @@
// natRuntime.cc - Implementation of native side of Runtime class.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
This file is part of libgcj.
@@ -21,7 +21,6 @@ details. */
#include <java/lang/Runtime.h>
#include <java/lang/UnknownError.h>
#include <java/lang/UnsatisfiedLinkError.h>
-#include <gnu/gcj/runtime/FileDeleter.h>
#include <gnu/gcj/runtime/FinalizerThread.h>
#include <java/io/File.h>
#include <java/util/TimeZone.h>
@@ -91,18 +90,19 @@ _Jv_FindSymbolInExecutable (const char *)
void
+java::lang::Runtime::runFinalizationForExit ()
+{
+ if (finalizeOnExit)
+ _Jv_RunAllFinalizers ();
+}
+
+void
java::lang::Runtime::exitInternal (jint status)
{
// Make status right for Unix. This is perhaps strange.
if (status < 0 || status > 255)
status = 255;
- if (finalizeOnExit)
- _Jv_RunAllFinalizers ();
-
- // Delete all files registered with File.deleteOnExit()
- gnu::gcj::runtime::FileDeleter::deleteOnExitNow ();
-
::exit (status);
}
diff --git a/libjava/java/lang/natThread.cc b/libjava/java/lang/natThread.cc
index 80cdae324ff..da9dcbabfd0 100644
--- a/libjava/java/lang/natThread.cc
+++ b/libjava/java/lang/natThread.cc
@@ -1,6 +1,6 @@
// natThread.cc - Native part of Thread class.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation
This file is part of libgcj.
@@ -213,8 +213,6 @@ java::lang::Thread::finish_ ()
}
#endif
- group = NULL;
-
// If a method cache was created, free it.
_Jv_FreeMethodCache();
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 490d2b1c127..09bca0b6f71 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -1,6 +1,6 @@
// prims.cc - Code for core of runtime environment.
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
This file is part of libgcj.
@@ -1387,10 +1387,10 @@ _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
_Jv_AttachCurrentThread (main_thread);
_Jv_ThreadRun (main_thread);
- _Jv_ThreadWait ();
- int status = (int) java::lang::ThreadGroup::had_uncaught_exception;
- runtime->exit (status);
+ // If we got here then something went wrong, as MainThread is not
+ // supposed to terminate.
+ ::exit (1);
}
void
diff --git a/libjava/sources.am b/libjava/sources.am
index d976154598b..043621ad632 100644
--- a/libjava/sources.am
+++ b/libjava/sources.am
@@ -555,7 +555,6 @@ gnu/gcj/io.list: $(gnu_gcj_io_source_files)
gnu_gcj_runtime_source_files = \
gnu/gcj/runtime/BootClassLoader.java \
gnu/gcj/runtime/ExtensionClassLoader.java \
-gnu/gcj/runtime/FileDeleter.java \
gnu/gcj/runtime/FinalizerThread.java \
gnu/gcj/runtime/HelperClassLoader.java \
gnu/gcj/runtime/JNIWeakRef.java \