Skip to content

Commit 861d57d

Browse files
committed
Thread termination note in isolate tear down
1 parent 9d87c20 commit 861d57d

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

espresso/src/com.oracle.truffle.espresso.mokapot/include/graal_isolate_dynamic.h

+12
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ typedef int (*graal_detach_thread_fn_t)(graal_isolatethread_t* thread);
127127
* waiting for any attached threads to detach from it, then discards its objects,
128128
* threads, and any other state or context that is associated with it.
129129
* Returns 0 on success, or a non-zero value on failure.
130+
*
131+
* If this call blocks indefinitely, this means there are still Java-application threads running.
132+
* To prevent indefinite blocking, these threads must be cooperatively shut down within Java before invoking this call.
133+
* To fix this use the option '-R:TearDownWarningSeconds=<secs>' at image build time to detect the threads that are still running.
134+
* This will print the stack traces of all threads that have not been cooperatively terminated.
135+
* Those threads need to be terminated from Java before calling tear_down_isolate.
130136
*/
131137
typedef int (*graal_tear_down_isolate_fn_t)(graal_isolatethread_t* isolateThread);
132138

@@ -141,6 +147,12 @@ typedef int (*graal_tear_down_isolate_fn_t)(graal_isolatethread_t* isolateThread
141147
* Java code at the time when this function is called or at any point in the future
142148
* or this will cause entirely undefined (and likely fatal) behavior.
143149
* Returns 0 on success, or a non-zero value on (non-fatal) failure.
150+
*
151+
* If this call blocks indefinitely, this means there are still Java-application threads running.
152+
* To prevent indefinite blocking, these threads must be cooperatively shut down within Java before invoking this call.
153+
* To fix this use the option '-R:TearDownWarningSeconds=<secs>' at image build time to detect the threads that are still running.
154+
* This will print the stack traces of all threads that have not been cooperatively terminated.
155+
* Those threads need to be terminated from Java before calling tear_down_isolate.
144156
*/
145157
typedef int (*graal_detach_all_threads_and_tear_down_isolate_fn_t)(graal_isolatethread_t* isolateThread);
146158

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

+28-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.core;
2626

27+
import static com.oracle.svm.core.SubstrateOptions.DeprecatedOptions.TearDownFailureNanos;
28+
import static com.oracle.svm.core.SubstrateOptions.DeprecatedOptions.TearDownWarningNanos;
2729
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.Immutable;
2830
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.IsolateCreationOnly;
2931
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.RelevantForCompilationIsolates;
@@ -63,6 +65,7 @@
6365
import com.oracle.svm.core.option.RuntimeOptionKey;
6466
import com.oracle.svm.core.option.SubstrateOptionsParser;
6567
import com.oracle.svm.core.thread.VMOperationControl;
68+
import com.oracle.svm.core.util.TimeUtils;
6669
import com.oracle.svm.core.util.UserError;
6770
import com.oracle.svm.util.LogUtils;
6871
import com.oracle.svm.util.ModuleSupport;
@@ -576,6 +579,13 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean o
576579
}
577580
}
578581
};
582+
583+
@Option(help = "The number of nanoseconds before and between which tearing down an isolate gives a warning message. 0 implies no warning.", deprecated = true, deprecationMessage = "Use TearDownWarningSeconds instead")//
584+
public static final RuntimeOptionKey<Long> TearDownWarningNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
585+
586+
@Option(help = "The number of nanoseconds before tearing down an isolate gives a failure message. 0 implies no message.", deprecated = true, deprecationMessage = "Use TearDownFailureSeconds instead")//
587+
public static final RuntimeOptionKey<Long> TearDownFailureNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
588+
579589
}
580590

581591
@Option(help = "Enable detection and runtime container configuration support.")//
@@ -818,18 +828,30 @@ private static void validateZapNativeMemory(HostedOptionKey<Boolean> optionKey)
818828
* Isolate tear down options.
819829
*/
820830

821-
@Option(help = "The number of nanoseconds before and between which tearing down an isolate gives a warning message. 0 implies no warning.")//
822-
public static final RuntimeOptionKey<Long> TearDownWarningNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
831+
@Option(help = "The number of seconds before and between which tearing down an isolate gives a warning message. 0 implies no warning.")//
832+
public static final RuntimeOptionKey<Long> TearDownWarningSeconds = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
823833

824-
@Option(help = "The number of nanoseconds before tearing down an isolate gives a failure message. 0 implies no message.")//
825-
public static final RuntimeOptionKey<Long> TearDownFailureNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
834+
@Option(help = "The number of seconds before tearing down an isolate gives a failure message. 0 implies no message.")//
835+
public static final RuntimeOptionKey<Long> TearDownFailureSeconds = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
826836

827837
public static long getTearDownWarningNanos() {
828-
return TearDownWarningNanos.getValue();
838+
if (TearDownWarningSeconds.hasBeenSet() && TearDownWarningNanos.hasBeenSet()) {
839+
throw new IllegalArgumentException("Can't set both TearDownWarningSeconds and TearDownWarningNanos at the same time. Use TearDownWarningSeconds.");
840+
}
841+
if (TearDownWarningNanos.hasBeenSet()) {
842+
return TearDownWarningNanos.getValue();
843+
}
844+
return TearDownWarningSeconds.getValue() * TimeUtils.nanosPerSecond;
829845
}
830846

831847
public static long getTearDownFailureNanos() {
832-
return TearDownFailureNanos.getValue();
848+
if (TearDownFailureSeconds.hasBeenSet() && TearDownFailureNanos.hasBeenSet()) {
849+
throw new IllegalArgumentException("Can't set both TearDownFailureSeconds and TearDownFailureNanos at the same time. Use TearDownFailureSeconds.");
850+
}
851+
if (TearDownFailureNanos.hasBeenSet()) {
852+
return TearDownFailureNanos.getValue();
853+
}
854+
return TearDownFailureSeconds.getValue() * TimeUtils.nanosPerSecond;
833855
}
834856

835857
@Option(help = "Define the maximum number of stores for which the loop that zeroes out objects is unrolled.")//

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointNativeFunctions.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import java.util.function.Function;
2828

29-
import jdk.graal.compiler.word.Word;
3029
import org.graalvm.nativeimage.CurrentIsolate;
3130
import org.graalvm.nativeimage.Isolate;
3231
import org.graalvm.nativeimage.IsolateThread;
@@ -41,6 +40,8 @@
4140
import com.oracle.svm.core.c.function.CEntryPointOptions.NoPrologue;
4241
import com.oracle.svm.core.thread.VMThreads;
4342

43+
import jdk.graal.compiler.word.Word;
44+
4445
@CHeader(value = GraalIsolateHeader.class)
4546
public final class CEntryPointNativeFunctions {
4647

@@ -158,12 +159,25 @@ public static int detachThread(IsolateThread thread) {
158159
return CEntryPointActions.leaveDetachThread();
159160
}
160161

162+
static final String THREAD_TERMINATION_NOTE_1 = "If this call blocks indefinitely, this means there are still Java-application threads running.";
163+
static final String THREAD_TERMINATION_NOTE_2 = "To prevent indefinite blocking, these threads must be cooperatively shut down within Java before invoking this call.";
164+
static final String THREAD_TERMINATION_NOTE_3 = "To fix this use the option '-R:TearDownWarningSeconds=<secs>' at image build time to detect the threads that are still running.";
165+
static final String THREAD_TERMINATION_NOTE_4 = "This will print the stack traces of all threads that have not been cooperatively terminated.";
166+
static final String THREAD_TERMINATION_NOTE_5 = "Those threads need to be terminated from Java before calling tear_down_isolate.";
167+
161168
@Uninterruptible(reason = UNINTERRUPTIBLE_REASON)
162169
@CEntryPoint(name = "tear_down_isolate", documentation = {
163170
"Tears down the isolate of the passed (and still attached) isolate thread,",
164171
"waiting for any attached threads to detach from it, then discards its objects,",
165172
"threads, and any other state or context that is associated with it.",
166-
"Returns 0 on success, or a non-zero value on failure."})
173+
"Returns 0 on success, or a non-zero value on failure.",
174+
"",
175+
THREAD_TERMINATION_NOTE_1,
176+
THREAD_TERMINATION_NOTE_2,
177+
THREAD_TERMINATION_NOTE_3,
178+
THREAD_TERMINATION_NOTE_4,
179+
THREAD_TERMINATION_NOTE_5
180+
})
167181
@CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, nameTransformation = NameTransformation.class)
168182
public static int tearDownIsolate(IsolateThread isolateThread) {
169183
int result = CEntryPointActions.enter(isolateThread);
@@ -184,7 +198,13 @@ public static int tearDownIsolate(IsolateThread isolateThread) {
184198
"None of the manually attached threads targeted by this function may be executing",
185199
"Java code at the time when this function is called or at any point in the future",
186200
"or this will cause entirely undefined (and likely fatal) behavior.",
187-
"Returns 0 on success, or a non-zero value on (non-fatal) failure."})
201+
"Returns 0 on success, or a non-zero value on (non-fatal) failure.",
202+
"",
203+
THREAD_TERMINATION_NOTE_1,
204+
THREAD_TERMINATION_NOTE_2,
205+
THREAD_TERMINATION_NOTE_3,
206+
THREAD_TERMINATION_NOTE_4,
207+
THREAD_TERMINATION_NOTE_5})
188208
@CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, nameTransformation = NameTransformation.class)
189209
public static int detachAllThreadsAndTearDownIsolate(IsolateThread isolateThread) {
190210
int result = CEntryPointActions.enter(isolateThread);

0 commit comments

Comments
 (0)