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
This commit is contained in:
Tom Tromey 2006-01-06 01:03:45 +00:00 committed by Tom Tromey
parent 0c158c887f
commit 1058a848dc
10 changed files with 122 additions and 96 deletions

View File

@ -1,3 +1,15 @@
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.

View File

@ -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 \

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}
/**
@ -667,6 +702,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.

View File

@ -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>
@ -90,6 +89,13 @@ _Jv_FindSymbolInExecutable (const char *)
void
java::lang::Runtime::runFinalizationForExit ()
{
if (finalizeOnExit)
_Jv_RunAllFinalizers ();
}
void
java::lang::Runtime::exitInternal (jint status)
{
@ -97,12 +103,6 @@ java::lang::Runtime::exitInternal (jint status)
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);
}

View File

@ -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();

View File

@ -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

View File

@ -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 \