Search in sources :

Example 1 with ThreadLeakScope

use of com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope in project randomizedtesting by randomizedtesting.

the class ThreadLeakControl method checkThreadLeaks.

/**
   * Perform a thread leak check at the given scope. 
   */
@SuppressWarnings("deprecation")
protected void checkThreadLeaks(Set<Thread> expectedState, List<Throwable> errors, LifecycleScope scope, Description description, AnnotatedElement... annotationChain) {
    final ThreadLeakScope annScope = firstAnnotated(ThreadLeakScope.class, annotationChain);
    // Return immediately if no checking.
    if (annScope.value() == Scope.NONE)
        return;
    // If suite scope check is requested skip testing at test level.
    if (annScope.value() == Scope.SUITE && scope == LifecycleScope.TEST) {
        return;
    }
    // Check for the set of live threads, with optional lingering. 
    int lingerTime = firstAnnotated(ThreadLeakLingering.class, annotationChain).linger();
    HashSet<Thread> threads = getThreads(suiteFilters);
    threads.removeAll(expectedState);
    if (lingerTime > 0 && !threads.isEmpty()) {
        final long deadline = System.currentTimeMillis() + lingerTime;
        try {
            LOGGER.warning("Will linger awaiting termination of " + threads.size() + " leaked thread(s).");
            do {
                // Check every few hundred milliseconds until deadline occurs. We want to break out
                // sooner than the maximum lingerTime but there is no explicit even that
                // would wake us up, so poll periodically.
                Thread.sleep(250);
                threads = getThreads(suiteFilters);
                threads.removeAll(expectedState);
                if (threads.isEmpty() || System.currentTimeMillis() > deadline)
                    break;
            } while (true);
        } catch (InterruptedException e) {
            LOGGER.warning("Lingering interrupted.");
        }
    }
    if (threads.isEmpty()) {
        return;
    }
    // Take one more snapshot, this time including stack traces (costly).
    HashMap<Thread, StackTraceElement[]> withTraces = getThreadsWithTraces(suiteFilters);
    withTraces.keySet().removeAll(expectedState);
    if (withTraces.isEmpty()) {
        return;
    }
    // Build up failure message (include stack traces of leaked threads).
    StringBuilder message = new StringBuilder(threads.size() + " thread" + (threads.size() == 1 ? "" : "s") + " leaked from " + scope + " scope at " + description + ": ");
    message.append(formatThreadStacks(withTraces));
    // The first exception is leaked threads error.
    errors.add(RandomizedRunner.augmentStackTrace(emptyStack(new ThreadLeakError(message.toString()))));
    // Perform actions on leaked threads.
    final EnumSet<Action> actions = EnumSet.noneOf(Action.class);
    actions.addAll(Arrays.asList(firstAnnotated(ThreadLeakAction.class, annotationChain).value()));
    if (actions.contains(Action.WARN)) {
        LOGGER.severe(message.toString());
    }
    Set<Thread> zombies = Collections.emptySet();
    if (actions.contains(Action.INTERRUPT)) {
        zombies = tryToInterruptAll(errors, withTraces.keySet());
    }
    // Process zombie thread check consequences here.
    if (!zombies.isEmpty()) {
        switch(firstAnnotated(ThreadLeakZombies.class, annotationChain).value()) {
            case CONTINUE:
                // Do nothing about it.
                break;
            case IGNORE_REMAINING_TESTS:
                // Mark zombie thread presence.
                RandomizedRunner.zombieMarker.set(true);
                break;
            default:
                throw new RuntimeException("Missing case.");
        }
    }
}
Also used : PrivilegedAction(java.security.PrivilegedAction) ThreadLeakAction(com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction) Action(com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action) ThreadLeakLingering(com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering) ThreadLeakAction(com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction) ThreadLeakZombies(com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies) ThreadLeakScope(com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope)

Aggregations

ThreadLeakAction (com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction)1 Action (com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction.Action)1 ThreadLeakLingering (com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering)1 ThreadLeakScope (com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope)1 ThreadLeakZombies (com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies)1 PrivilegedAction (java.security.PrivilegedAction)1