diff options
Diffstat (limited to 'libjava/java')
-rw-r--r-- | libjava/java/io/File.java | 5 | ||||
-rw-r--r-- | libjava/java/lang/Runtime.java | 120 | ||||
-rw-r--r-- | libjava/java/lang/natRuntime.cc | 16 | ||||
-rw-r--r-- | libjava/java/lang/natThread.cc | 4 |
4 files changed, 91 insertions, 54 deletions
diff --git a/libjava/java/io/File.java b/libjava/java/io/File.java index e3d59cb..1b02b60 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 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. diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc index 300dc57..5cca1b0 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 80cdae3..da9dcba 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(); |