aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang/Runtime.java
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2006-01-06 01:03:45 +0000
committerTom Tromey <tromey@gcc.gnu.org>2006-01-06 01:03:45 +0000
commit1058a848dcd220965dd4d126eb9f4159782dd586 (patch)
treeb1406d0aef45f9b54fc3cb3b56375bc3ce39b15c /libjava/java/lang/Runtime.java
parent0c158c887f3669dd47297b68b1aa490f5da5b7ad (diff)
downloadgcc-1058a848dcd220965dd4d126eb9f4159782dd586.zip
gcc-1058a848dcd220965dd4d126eb9f4159782dd586.tar.gz
gcc-1058a848dcd220965dd4d126eb9f4159782dd586.tar.bz2
natThread.cc (finish_): Don't clear 'group'.
* 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. From-SVN: r109400
Diffstat (limited to 'libjava/java/lang/Runtime.java')
-rw-r--r--libjava/java/lang/Runtime.java120
1 files changed, 80 insertions, 40 deletions
diff --git a/libjava/java/lang/Runtime.java b/libjava/java/lang/Runtime.java
index a30a44b..519b4ac 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.