# HG changeset patch # User chegar # Date 1297859893 0 # Node ID ffe782989540a74bb8f0efd28320777963ca7903 # Parent 3a07aee44a7658dcba9c8c36adc0ba9668f8a09c 6562203: Thread doesn't terminate immediately if it was stopped before start Reviewed-by: dholmes, alanb diff -r 3a07aee44a76 -r ffe782989540 jdk/src/share/classes/java/lang/Thread.java --- a/jdk/src/share/classes/java/lang/Thread.java Tue Feb 15 08:34:33 2011 -0800 +++ b/jdk/src/share/classes/java/lang/Thread.java Wed Feb 16 12:38:13 2011 +0000 @@ -254,12 +254,6 @@ */ public final static int MAX_PRIORITY = 10; - /* If stop was called before start */ - private boolean stopBeforeStart; - - /* Remembered Throwable from stop before start */ - private Throwable throwableFromStop; - /** * Returns a reference to the currently executing thread object. * @@ -706,10 +700,6 @@ it will be passed up the call stack */ } } - - if (stopBeforeStart) { - stop0(throwableFromStop); - } } private native void start0(); @@ -820,12 +810,7 @@ */ @Deprecated public final void stop() { - // If the thread is already dead, return. - // A zero status value corresponds to "NEW". - if ((threadStatus != 0) && !isAlive()) { - return; - } - stop1(new ThreadDeath()); + stop(new ThreadDeath()); } /** @@ -879,36 +864,25 @@ */ @Deprecated public final synchronized void stop(Throwable obj) { - stop1(obj); - } + if (obj == null) + throw new NullPointerException(); - /** - * Common impl for stop() and stop(Throwable). - */ - private final synchronized void stop1(Throwable th) { SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if ((this != Thread.currentThread()) || - (!(th instanceof ThreadDeath))) { + (!(obj instanceof ThreadDeath))) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } - // A zero status value corresponds to "NEW" + // A zero status value corresponds to "NEW", it can't change to + // not-NEW because we hold the lock. if (threadStatus != 0) { resume(); // Wake up thread if it was suspended; no-op otherwise - stop0(th); - } else { + } - // Must do the null arg check that the VM would do with stop0 - if (th == null) { - throw new NullPointerException(); - } - - // Remember this stop attempt for if/when start is used - stopBeforeStart = true; - throwableFromStop = th; - } + // The VM can handle all thread states + stop0(obj); } /** diff -r 3a07aee44a76 -r ffe782989540 jdk/test/java/lang/Thread/StopBeforeStart.java --- a/jdk/test/java/lang/Thread/StopBeforeStart.java Tue Feb 15 08:34:33 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4519200 - * @summary Confirm a Thread.stop before start complies with the spec - * @author Pete Soper - * - * Confirm that a thread that had its stop method invoked before start - * does properly terminate with expected exception behavior. NOTE that - * arbitrary application threads could return from their run methods faster - * than the VM can throw an async exception. - */ -public class StopBeforeStart { - - private static final int JOIN_TIMEOUT=10000; - - private class MyThrowable extends Throwable { - } - - private class Catcher implements Thread.UncaughtExceptionHandler { - private boolean nullaryStop; - private Throwable theThrowable; - private Throwable expectedThrowable; - private boolean exceptionThrown; - - Catcher(boolean nullaryStop) { - this.nullaryStop = nullaryStop; - if (!nullaryStop) { - expectedThrowable = new MyThrowable(); - } - } - - public void uncaughtException(Thread t, Throwable th) { - exceptionThrown = true; - theThrowable = th; - } - - void check(String label) throws Throwable { - if (!exceptionThrown) { - throw new RuntimeException(label + - " test:" + " missing uncaught exception"); - } - - if (nullaryStop) { - if (! (theThrowable instanceof ThreadDeath)) { - throw new RuntimeException(label + - " test:" + " expected ThreadDeath in uncaught handler"); - } - } else if (theThrowable != expectedThrowable) { - throw new RuntimeException(label + - " test:" + " wrong Throwable in uncaught handler"); - } - } - } - - private class MyRunnable implements Runnable { - public void run() { - while(true) - ; - } - } - - private class MyThread extends Thread { - public void run() { - while(true) - ; - } - } - - - public static void main(String args[]) throws Throwable { - (new StopBeforeStart()).doit(); - System.out.println("Test passed"); - } - - private void doit() throws Throwable { - - runit(false, new Thread(new MyRunnable()),"Thread"); - runit(true, new Thread(new MyRunnable()),"Thread"); - runit(false, new MyThread(),"Runnable"); - runit(true, new MyThread(),"Runnable"); - } - - private void runit(boolean nullaryStop, Thread thread, - String type) throws Throwable { - - Catcher c = new Catcher(nullaryStop); - thread.setUncaughtExceptionHandler(c); - - if (nullaryStop) { - thread.stop(); - } else { - thread.stop(c.expectedThrowable); - } - - thread.start(); - thread.join(JOIN_TIMEOUT); - - if (thread.getState() != Thread.State.TERMINATED) { - - thread.stop(); - - // Under high load this could be a false positive - throw new RuntimeException(type + - " test:" + " app thread did not terminate"); - } - - c.check(type); - } -}