Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6704979

(thread) LogManager.Cleaner shutdown hook in JDK 5 can run in destroyed thread group

    XMLWordPrintable

Details

    • Bug
    • Resolution: Not an Issue
    • P3
    • tbd
    • 5.0u15
    • core-libs

    Backports

      Description

        Run the following program under JDK 5:

        ---%<---
        import java.util.logging.Logger;
        public class TestLogManagerCleaner {
            public static void main(String[] args) throws InterruptedException {
                ThreadGroup g = new ThreadGroup("my group");
                Thread t = new Thread(g, new Runnable() {
                    public void run() {
                        Logger.getAnonymousLogger().info("used the logger");
                    }
                }, "my thread");
                t.start();
                t.join();
                g.destroy();
                System.exit(0);
            }
        }
        ---%<---

        On Ubuntu 8.04, I get a nonzero VM exit status and a stack trace:

        ---%<---
        java version "1.5.0_15"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_15-b04)
        Java HotSpot(TM) Server VM (build 1.5.0_15-b04, mixed mode)

        May 20, 2008 11:48:21 AM TestLogManagerCleaner$1 run
        INFO: used the logger
        Exception in thread "main" java.lang.IllegalThreadStateException
                at java.lang.ThreadGroup.add(ThreadGroup.java:856)
                at java.lang.Thread.start(Thread.java:573)
                at java.lang.Shutdown.runHooks(Shutdown.java:128)
                at java.lang.Shutdown.sequence(Shutdown.java:173)
                at java.lang.Shutdown.exit(Shutdown.java:218)
                at java.lang.Runtime.exit(Runtime.java:90)
                at java.lang.System.exit(System.java:869)
                at TestLogManagerCleaner.main(TestLogManagerCleaner.java:13)
        ---%<---

        I do not get this error in JDK 6 or 7, though I do not yet know why.

        If I prepend a patched version of ThreadGroup.java

        ---%<---
                    // ... as before ...
        if (destroyed) {
                        Object target = null;
                        try {
                            Field f = Thread.class.getDeclaredField("target");
                            f.setAccessible(true);
                            target = f.get(t);
                        } catch (Exception x) {
                            x.printStackTrace();
                        }
        throw new IllegalThreadStateException("cannot add thread " + t + " of " + t.getClass() + " with target " + target + " to destroyed group " + this + " of " + getClass() + " with current threads " + Arrays.toString(threads));
        }
                    // ... as before ...
        ---%<---

        then I can see the real problem:

        ---%<---
        ...
        Exception in thread "main" java.lang.IllegalThreadStateException: cannot add thread Thread[Thread-0,5,my group] of class java.util.logging.LogManager$Cleaner with target null to destroyed group java.lang.ThreadGroup[name=my group,maxpri=10] of class java.lang.ThreadGroup with current threads null
        ...
        ---%<---

        It seems that LogManager's static block registers a VM shutdown hook from the calling thread's group. This is unsafe since there is no guarantee that this group is not an application thread group that might be destroyed before the VM exits.

        Observed initially in NetBeans unit tests relating to thread groups. The test passes but the VM (and thus the Ant <junit> task) aborts:

            [junit] Testsuite: org.netbeans.core.execution.CoreExecutionCompatibilityTest
            [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.238 sec
            [junit]
            [junit] Exception in thread "main" java.lang.IllegalThreadStateException
            [junit] at java.lang.ThreadGroup.add(ThreadGroup.java:856)
            [junit] at java.lang.Thread.start(Thread.java:573)
            [junit] at java.lang.Shutdown.runHooks(Shutdown.java:128)
            [junit] at java.lang.Shutdown.sequence(Shutdown.java:173)
            [junit] at java.lang.Shutdown.exit(Shutdown.java:218)
            [junit] at java.lang.Runtime.exit(Runtime.java:90)
            [junit] at java.lang.System.exit(System.java:869)
            [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:773)
            [junit] Test org.netbeans.core.execution.CoreExecutionCompatibilityTest FAILED

        Googling some key terms shows that this is not completely isolated:

        http://tech.groups.yahoo.com/group/junitperf/message/84

        Attachments

          Issue Links

            Activity

              People

                chegar Chris Hegarty
                jglick Jesse Glick (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: