--- old/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java Mon Jun 25 21:04:20 2012 +++ new/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java Mon Jun 25 21:04:19 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -25,6 +25,15 @@ package com.sun.corba.se.impl.orbutil.threadpool; +import java.io.IOException; + +import java.security.PrivilegedAction; +import java.security.AccessController; + +import java.util.concurrent.atomic.AtomicInteger; + +import com.sun.corba.se.spi.orb.ORB; + import com.sun.corba.se.spi.orbutil.threadpool.NoSuchThreadPoolException; import com.sun.corba.se.spi.orbutil.threadpool.ThreadPool; import com.sun.corba.se.spi.orbutil.threadpool.ThreadPoolManager; @@ -33,23 +42,104 @@ import com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl; import com.sun.corba.se.impl.orbutil.ORBConstants; +import com.sun.corba.se.impl.logging.ORBUtilSystemException; +import com.sun.corba.se.impl.orbutil.ORBConstants; +import com.sun.corba.se.spi.logging.CORBALogDomains; + + public class ThreadPoolManagerImpl implements ThreadPoolManager { - private ThreadPool threadPool ; + private ThreadPool threadPool; + private ThreadGroup threadGroup; - public ThreadPoolManagerImpl( ThreadGroup tg ) - { - // Use unbounded threadpool in J2SE ORB - // ThreadPoolManager from s1as appserver code base can be set in the - // ORB. ThreadPools in the appserver are bounded. In that situation - // the ThreadPool in this ThreadPoolManager will have its threads - // die after the idle timeout. - // XXX Should there be cleanup when ORB.shutdown is called if the - // ORB owns the ThreadPool? - threadPool = new ThreadPoolImpl( tg, - ORBConstants.THREADPOOL_DEFAULT_NAME ) ; + private static final ORBUtilSystemException wrapper = + ORBUtilSystemException.get(CORBALogDomains.RPC_TRANSPORT); + + public ThreadPoolManagerImpl() { + threadGroup = getThreadGroup(); + threadPool = new ThreadPoolImpl(threadGroup, + ORBConstants.THREADPOOL_DEFAULT_NAME); } + private static AtomicInteger tgCount = new AtomicInteger(); + + + private ThreadGroup getThreadGroup() { + ThreadGroup tg; + + // See bugs 4916766 and 4936203 + // We intend to create new threads in a reliable thread group. + // This avoids problems if the application/applet + // creates a thread group, makes JavaIDL calls which create a new + // connection and ReaderThread, and then destroys the thread + // group. If our ReaderThreads were to be part of such destroyed thread + // group then it might get killed and cause other invoking threads + // sharing the same connection to get a non-restartable + // CommunicationFailure. We'd like to avoid that. + // + // Our solution is to create all of our threads in the highest thread + // group that we have access to, given our own security clearance. + // + try { + // try to get a thread group that's as high in the threadgroup + // parent-child hierarchy, as we can get to. + // this will prevent an ORB thread created during applet-init from + // being killed when an applet dies. + tg = AccessController.doPrivileged( + new PrivilegedAction() { + public ThreadGroup run() { + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + ThreadGroup ptg = tg; + try { + while (ptg != null) { + tg = ptg; + ptg = tg.getParent(); + } + } catch (SecurityException se) { + // Discontinue going higher on a security exception. + } + return new ThreadGroup(tg, "ORB ThreadGroup " + tgCount.getAndIncrement()); + } + } + ); + } catch (SecurityException e) { + // something wrong, we go back to the original code + tg = Thread.currentThread().getThreadGroup(); + } + + return tg; + } + + public void close() { + try { + threadPool.close(); + } catch (IOException exc) { + wrapper.threadPoolCloseError(); + } + + try { + boolean isDestroyed = threadGroup.isDestroyed(); + int numThreads = threadGroup.activeCount(); + int numGroups = threadGroup.activeGroupCount(); + + if (isDestroyed) { + wrapper.threadGroupIsDestroyed(threadGroup); + } else { + if (numThreads > 0) + wrapper.threadGroupHasActiveThreadsInClose(threadGroup, numThreads); + + if (numGroups > 0) + wrapper.threadGroupHasSubGroupsInClose(threadGroup, numGroups); + + threadGroup.destroy(); + } + } catch (IllegalThreadStateException exc) { + wrapper.threadGroupDestroyFailed(exc, threadGroup); + } + + threadGroup = null; + } + /** * This method will return an instance of the threadpool given a threadpoolId, * that can be used by any component in the app. server.