55
66package io .opentelemetry .sdk .internal ;
77
8- import io .opentelemetry .context .Context ;
98import java .util .concurrent .Executors ;
109import java .util .concurrent .ThreadFactory ;
1110import java .util .concurrent .atomic .AtomicInteger ;
11+ import javax .annotation .Nullable ;
1212
1313/**
1414 * A {@link ThreadFactory} that delegates to {@code Executors.defaultThreadFactory()} and marks all
2020public final class DaemonThreadFactory implements ThreadFactory {
2121 private final String namePrefix ;
2222 private final AtomicInteger counter = new AtomicInteger ();
23- private final ThreadFactory delegate = Executors .defaultThreadFactory ();
24- private final boolean propagateContextForTesting ;
23+ private final ThreadFactory delegate ;
2524
2625 public DaemonThreadFactory (String namePrefix ) {
27- this (namePrefix , /* propagateContextForTesting= */ false );
26+ this (namePrefix , Executors . defaultThreadFactory () );
2827 }
2928
3029 /**
3130 * {@link DaemonThreadFactory}'s constructor.
3231 *
3332 * @param namePrefix Used when setting the new thread's name.
34- * @param propagateContextForTesting For tests only. When enabled, the current thread's {@link
35- * Context} will be passed over to the new threads, this is useful for validating scenarios
36- * where context propagation is available through bytecode instrumentation.
33+ * @param delegate Delegate to create threads.
3734 */
38- public DaemonThreadFactory (String namePrefix , boolean propagateContextForTesting ) {
35+ public DaemonThreadFactory (String namePrefix , ThreadFactory delegate ) {
3936 this .namePrefix = namePrefix ;
40- this .propagateContextForTesting = propagateContextForTesting ;
37+ this .delegate = delegate ;
4138 }
4239
4340 @ Override
4441 public Thread newThread (Runnable runnable ) {
45- Thread t =
46- delegate . newThread (
47- propagateContextForTesting ? Context . current (). wrap ( runnable ) : runnable );
42+ Thread t = delegate . newThread ( runnable );
43+ t . setUncaughtExceptionHandler (
44+ new ManagedUncaughtExceptionHandler ( t . getUncaughtExceptionHandler ()) );
4845 try {
4946 t .setDaemon (true );
5047 t .setName (namePrefix + "-" + counter .incrementAndGet ());
@@ -53,4 +50,22 @@ public Thread newThread(Runnable runnable) {
5350 }
5451 return t ;
5552 }
53+
54+ static class ManagedUncaughtExceptionHandler implements Thread .UncaughtExceptionHandler {
55+ @ Nullable private final Thread .UncaughtExceptionHandler delegate ;
56+
57+ private ManagedUncaughtExceptionHandler (@ Nullable Thread .UncaughtExceptionHandler delegate ) {
58+ this .delegate = delegate ;
59+ }
60+
61+ @ SuppressWarnings ("Interruption" )
62+ @ Override
63+ public void uncaughtException (Thread t , Throwable e ) {
64+ if (e instanceof InterruptedException ) {
65+ t .interrupt ();
66+ } else if (delegate != null ) {
67+ delegate .uncaughtException (t , e );
68+ }
69+ }
70+ }
5671}
0 commit comments