summaryrefslogtreecommitdiff
path: root/java/openjdk6/files/icedtea/security/20130201/6776941.patch
diff options
context:
space:
mode:
Diffstat (limited to 'java/openjdk6/files/icedtea/security/20130201/6776941.patch')
-rw-r--r--java/openjdk6/files/icedtea/security/20130201/6776941.patch272
1 files changed, 0 insertions, 272 deletions
diff --git a/java/openjdk6/files/icedtea/security/20130201/6776941.patch b/java/openjdk6/files/icedtea/security/20130201/6776941.patch
deleted file mode 100644
index 7604b50b9b22..000000000000
--- a/java/openjdk6/files/icedtea/security/20130201/6776941.patch
+++ /dev/null
@@ -1,272 +0,0 @@
-# HG changeset patch
-# User dholmes
-# Date 1350872930 14400
-# Node ID 6088f35106866940de257456c8eee21b130d5ff5
-# Parent 21487ef30163da2a96369eee80a3bf5e94612017
-6776941: Improve thread pool shutdown
-Reviewed-by: dl, skoivu
-
-diff --git a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
---- jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
-+++ jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
-@@ -34,8 +34,10 @@
- */
-
- package java.util.concurrent;
--import java.util.concurrent.locks.*;
--import java.util.concurrent.atomic.*;
-+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
-+import java.util.concurrent.locks.Condition;
-+import java.util.concurrent.locks.ReentrantLock;
-+import java.util.concurrent.atomic.AtomicInteger;
- import java.util.*;
-
- /**
-@@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends
- * policy limiting the number of threads. Even though it is not
- * treated as an error, failure to create threads may result in
- * new tasks being rejected or existing ones remaining stuck in
-- * the queue. On the other hand, no special precautions exist to
-- * handle OutOfMemoryErrors that might be thrown while trying to
-- * create threads, since there is generally no recourse from
-- * within this class.
-+ * the queue.
-+ *
-+ * We go further and preserve pool invariants even in the face of
-+ * errors such as OutOfMemoryError, that might be thrown while
-+ * trying to create threads. Such errors are rather common due to
-+ * the need to allocate a native stack in Thread#start, and users
-+ * will want to perform clean pool shutdown to clean up. There
-+ * will likely be enough memory available for the cleanup code to
-+ * complete without encountering yet another OutOfMemoryError.
- */
- private volatile ThreadFactory threadFactory;
-
-@@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends
- * task execution. This protects against interrupts that are
- * intended to wake up a worker thread waiting for a task from
- * instead interrupting a task being run. We implement a simple
-- * non-reentrant mutual exclusion lock rather than use ReentrantLock
-- * because we do not want worker tasks to be able to reacquire the
-- * lock when they invoke pool control methods like setCorePoolSize.
-+ * non-reentrant mutual exclusion lock rather than use
-+ * ReentrantLock because we do not want worker tasks to be able to
-+ * reacquire the lock when they invoke pool control methods like
-+ * setCorePoolSize. Additionally, to suppress interrupts until
-+ * the thread actually starts running tasks, we initialize lock
-+ * state to a negative value, and clear it upon start (in
-+ * runWorker).
- */
- private final class Worker
- extends AbstractQueuedSynchronizer
-@@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends
- * @param firstTask the first task (null if none)
- */
- Worker(Runnable firstTask) {
-+ setState(-1); // inhibit interrupts until runWorker
- this.firstTask = firstTask;
- this.thread = getThreadFactory().newThread(this);
- }
-@@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends
- // The value 1 represents the locked state.
-
- protected boolean isHeldExclusively() {
-- return getState() == 1;
-+ return getState() != 0;
- }
-
- protected boolean tryAcquire(int unused) {
-@@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends
- public boolean tryLock() { return tryAcquire(1); }
- public void unlock() { release(1); }
- public boolean isLocked() { return isHeldExclusively(); }
-+
-+ void interruptIfStarted() {
-+ Thread t;
-+ if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
-+ try {
-+ t.interrupt();
-+ } catch (SecurityException ignore) {
-+ }
-+ }
-+ }
- }
-
- /*
-@@ -729,10 +751,7 @@ public class ThreadPoolExecutor extends
- mainLock.lock();
- try {
- for (Worker w : workers) {
-- try {
-- w.thread.interrupt();
-- } catch (SecurityException ignore) {
-- }
-+ w.interruptIfStarted();
- }
- } finally {
- mainLock.unlock();
-@@ -789,19 +808,6 @@ public class ThreadPoolExecutor extends
- }
-
- private static final boolean ONLY_ONE = true;
--
-- /**
-- * Ensures that unless the pool is stopping, the current thread
-- * does not have its interrupt set. This requires a double-check
-- * of state in case the interrupt was cleared concurrently with a
-- * shutdownNow -- if so, the interrupt is re-enabled.
-- */
-- private void clearInterruptsForTaskRun() {
-- if (runStateLessThan(ctl.get(), STOP) &&
-- Thread.interrupted() &&
-- runStateAtLeast(ctl.get(), STOP))
-- Thread.currentThread().interrupt();
-- }
-
- /*
- * Misc utilities, most of which are also exported to
-@@ -862,12 +868,13 @@ public class ThreadPoolExecutor extends
- * Checks if a new worker can be added with respect to current
- * pool state and the given bound (either core or maximum). If so,
- * the worker count is adjusted accordingly, and, if possible, a
-- * new worker is created and started running firstTask as its
-+ * new worker is created and started, running firstTask as its
- * first task. This method returns false if the pool is stopped or
- * eligible to shut down. It also returns false if the thread
-- * factory fails to create a thread when asked, which requires a
-- * backout of workerCount, and a recheck for termination, in case
-- * the existence of this worker was holding up termination.
-+ * factory fails to create a thread when asked. If the thread
-+ * creation fails, either due to the thread factory returning
-+ * null, or due to an exception (typically OutOfMemoryError in
-+ * Thread#start), we roll back cleanly.
- *
- * @param firstTask the task the new thread should run first (or
- * null if none). Workers are created with an initial first task
-@@ -910,46 +917,65 @@ public class ThreadPoolExecutor extends
- }
- }
-
-- Worker w = new Worker(firstTask);
-- Thread t = w.thread;
-+ boolean workerStarted = false;
-+ boolean workerAdded = false;
-+ Worker w = null;
-+ try {
-+ final ReentrantLock mainLock = this.mainLock;
-+ w = new Worker(firstTask);
-+ final Thread t = w.thread;
-+ if (t != null) {
-+ mainLock.lock();
-+ try {
-+ // Recheck while holding lock.
-+ // Back out on ThreadFactory failure or if
-+ // shut down before lock acquired.
-+ int c = ctl.get();
-+ int rs = runStateOf(c);
-
-+ if (rs < SHUTDOWN ||
-+ (rs == SHUTDOWN && firstTask == null)) {
-+ if (t.isAlive()) // precheck that t is startable
-+ throw new IllegalThreadStateException();
-+ workers.add(w);
-+ int s = workers.size();
-+ if (s > largestPoolSize)
-+ largestPoolSize = s;
-+ workerAdded = true;
-+ }
-+ } finally {
-+ mainLock.unlock();
-+ }
-+ if (workerAdded) {
-+ t.start();
-+ workerStarted = true;
-+ }
-+ }
-+ } finally {
-+ if (! workerStarted)
-+ addWorkerFailed(w);
-+ }
-+ return workerStarted;
-+ }
-+
-+ /**
-+ * Rolls back the worker thread creation.
-+ * - removes worker from workers, if present
-+ * - decrements worker count
-+ * - rechecks for termination, in case the existence of this
-+ * worker was holding up termination
-+ */
-+ private void addWorkerFailed(Worker w) {
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
-- // Recheck while holding lock.
-- // Back out on ThreadFactory failure or if
-- // shut down before lock acquired.
-- int c = ctl.get();
-- int rs = runStateOf(c);
--
-- if (t == null ||
-- (rs >= SHUTDOWN &&
-- ! (rs == SHUTDOWN &&
-- firstTask == null))) {
-- decrementWorkerCount();
-- tryTerminate();
-- return false;
-- }
--
-- workers.add(w);
--
-- int s = workers.size();
-- if (s > largestPoolSize)
-- largestPoolSize = s;
-+ if (w != null)
-+ workers.remove(w);
-+ decrementWorkerCount();
-+ tryTerminate();
- } finally {
- mainLock.unlock();
- }
--
-- t.start();
-- // It is possible (but unlikely) for a thread to have been
-- // added to workers, but not yet started, during transition to
-- // STOP, which could result in a rare missed interrupt,
-- // because Thread.interrupt is not guaranteed to have any effect
-- // on a non-yet-started Thread (see Thread#interrupt).
-- if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
-- t.interrupt();
--
-- return true;
- }
-
- /**
-@@ -1096,15 +1122,25 @@ public class ThreadPoolExecutor extends
- * @param w the worker
- */
- final void runWorker(Worker w) {
-+ Thread wt = Thread.currentThread();
- Runnable task = w.firstTask;
- w.firstTask = null;
-+ w.unlock(); // allow interrupts
- boolean completedAbruptly = true;
- try {
- while (task != null || (task = getTask()) != null) {
- w.lock();
-- clearInterruptsForTaskRun();
-+ // If pool is stopping, ensure thread is interrupted;
-+ // if not, ensure thread is not interrupted. This
-+ // requires a recheck in second case to deal with
-+ // shutdownNow race while clearing interrupt
-+ if ((runStateAtLeast(ctl.get(), STOP) ||
-+ (Thread.interrupted() &&
-+ runStateAtLeast(ctl.get(), STOP))) &&
-+ !wt.isInterrupted())
-+ wt.interrupt();
- try {
-- beforeExecute(w.thread, task);
-+ beforeExecute(wt, task);
- Throwable thrown = null;
- try {
- task.run();