undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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
|
||||
* @run testng AsyncShutdownNowInvokeAnyRace
|
||||
* @summary A variant of AsyncShutdownNow useful for race bug hunting
|
||||
*/
|
||||
|
||||
// TODO: reorganize all of the AsyncShutdown tests
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.LockInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class AsyncShutdownNowInvokeAnyRace {
|
||||
|
||||
// TODO: even more jitter-inducing parallelism?
|
||||
|
||||
// int nThreads = ThreadLocalRandom.current().nextInt(1, 50);
|
||||
// ExecutorService pool = Executors.newCachedThreadPool();
|
||||
// Callable<Void> task = () -> { testInvokeAny_1(); return null; };
|
||||
// List<Callable<Void>> tasks = Collections.nCopies(nThreads, task);
|
||||
// try {
|
||||
// for (Future<Void> future : pool.invokeAll(tasks)) {
|
||||
// future.get();
|
||||
// }
|
||||
// } finally {
|
||||
// pool.shutdown();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void testInvokeAny_1() throws Exception {
|
||||
|
||||
/**
|
||||
* Test shutdownNow with thread blocked in invokeAny.
|
||||
*/
|
||||
@Test
|
||||
public void testInvokeAny() throws Exception {
|
||||
final int reps = 30_000;
|
||||
ThreadLocalRandom rnd = ThreadLocalRandom.current();
|
||||
int falseAlarms = 0;
|
||||
for (int rep = 1; rep < reps; rep++) {
|
||||
ForkJoinPool pool = new ForkJoinPool(1);
|
||||
CountDownLatch pleaseShutdownNow = new CountDownLatch(1);
|
||||
int nTasks = rnd.nextInt(2, 5);
|
||||
AtomicInteger threadsStarted = new AtomicInteger(0);
|
||||
AtomicReference<String> poolAtShutdownNow = new AtomicReference<>();
|
||||
Callable<Void> blockPool = () -> {
|
||||
threadsStarted.getAndIncrement();
|
||||
// await submission quiescence; may false-alarm
|
||||
// TODO: consider re-checking to reduce false alarms
|
||||
while (threadsStarted.get() + pool.getQueuedSubmissionCount() < nTasks)
|
||||
Thread.yield();
|
||||
pleaseShutdownNow.countDown();
|
||||
Thread.sleep(86400_000);
|
||||
return null;
|
||||
};
|
||||
List<Callable<Void>> tasks = Collections.nCopies(nTasks, blockPool);
|
||||
Runnable shutdown = () -> {
|
||||
try {
|
||||
pleaseShutdownNow.await();
|
||||
poolAtShutdownNow.set(pool.toString());
|
||||
pool.shutdownNow();
|
||||
} catch (Throwable t) { throw new AssertionError(t); }
|
||||
};
|
||||
Future<Void> shutdownResult = CompletableFuture.runAsync(shutdown);
|
||||
try {
|
||||
try {
|
||||
if (rnd.nextBoolean())
|
||||
pool.invokeAny(tasks, 10L, SECONDS);
|
||||
else
|
||||
pool.invokeAny(tasks);
|
||||
throw new AssertionError("should throw");
|
||||
} catch (RejectedExecutionException re) {
|
||||
falseAlarms++;
|
||||
} catch (CancellationException re) {
|
||||
} catch (ExecutionException ex) {
|
||||
Throwable cause = ex.getCause();
|
||||
if (!(cause instanceof InterruptedException) &&
|
||||
!(cause instanceof CancellationException))
|
||||
throw ex;
|
||||
} catch (TimeoutException ex) {
|
||||
dumpTestThreads();
|
||||
int i = rep;
|
||||
String detail = String.format(
|
||||
"invokeAny timed out, "
|
||||
+ "nTasks=%d rep=%d threadsStarted=%d%n"
|
||||
+ "poolAtShutdownNow=%s%n"
|
||||
+ "poolAtTimeout=%s%n"
|
||||
+ "queuedTaskCount=%d queuedSubmissionCount=%d",
|
||||
nTasks, i, threadsStarted.get(),
|
||||
poolAtShutdownNow,
|
||||
pool,
|
||||
pool.getQueuedTaskCount(),
|
||||
pool.getQueuedSubmissionCount());
|
||||
throw new AssertionError(detail, ex);
|
||||
}
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
if (falseAlarms != 0)
|
||||
System.out.println("Premature shutdowns = " + falseAlarms);
|
||||
shutdownResult.get();
|
||||
}
|
||||
}
|
||||
|
||||
//--- thread stack dumping (from JSR166TestCase.java) ---
|
||||
|
||||
private static final ThreadMXBean THREAD_MXBEAN
|
||||
= ManagementFactory.getThreadMXBean();
|
||||
|
||||
/** Returns true if thread info might be useful in a thread dump. */
|
||||
static boolean threadOfInterest(ThreadInfo info) {
|
||||
final String name = info.getThreadName();
|
||||
String lockName;
|
||||
if (name == null)
|
||||
return true;
|
||||
if (name.equals("Signal Dispatcher")
|
||||
|| name.equals("WedgedTestDetector"))
|
||||
return false;
|
||||
if (name.equals("Reference Handler")) {
|
||||
// Reference Handler stacktrace changed in JDK-8156500
|
||||
StackTraceElement[] stackTrace; String methodName;
|
||||
if ((stackTrace = info.getStackTrace()) != null
|
||||
&& stackTrace.length > 0
|
||||
&& (methodName = stackTrace[0].getMethodName()) != null
|
||||
&& methodName.equals("waitForReferencePendingList"))
|
||||
return false;
|
||||
// jdk8 Reference Handler stacktrace
|
||||
if ((lockName = info.getLockName()) != null
|
||||
&& lockName.startsWith("java.lang.ref"))
|
||||
return false;
|
||||
}
|
||||
if ((name.equals("Finalizer") || name.equals("Common-Cleaner"))
|
||||
&& (lockName = info.getLockName()) != null
|
||||
&& lockName.startsWith("java.lang.ref"))
|
||||
return false;
|
||||
if (name.startsWith("ForkJoinPool.commonPool-worker")
|
||||
&& (lockName = info.getLockName()) != null
|
||||
&& lockName.startsWith("java.util.concurrent.ForkJoinPool"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A debugging tool to print stack traces of most threads, as jstack does.
|
||||
* Uninteresting threads are filtered out.
|
||||
*/
|
||||
static void dumpTestThreads() {
|
||||
System.err.println("------ stacktrace dump start ------");
|
||||
for (ThreadInfo info : THREAD_MXBEAN.dumpAllThreads(true, true))
|
||||
if (threadOfInterest(info))
|
||||
System.err.print(info);
|
||||
System.err.println("------ stacktrace dump end ------");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue