Issues with dtraceasm, and a workaround

Aleksey Shipilev shade at redhat.com
Thu Feb 18 12:24:21 UTC 2021


On 2/18/21 1:14 PM, Aleksey Shipilev wrote:
> Hi,
> 
> On 1/25/21 6:16 PM, Paul Sandoz wrote:
>> Sending a TERM signal before destroying the process works around this issue (see patch below).
>> It kicks the dtrace process, resulting in the process relinquishing the remaining dtrace output
>> to theoutput file.
> 
> This is weird!
> 
>> --- a/jmh-core/src/main/java/org/openjdk/jmh/profile/DTraceAsmProfiler.java
>> +++ b/jmh-core/src/main/java/org/openjdk/jmh/profile/DTraceAsmProfiler.java
>> @@ -87,6 +87,9 @@ public class DTraceAsmProfiler extends AbstractPerfAsmProfiler {
>>                throw new IllegalStateException("DTrace needs the forked VM PID, but it is not initialized");
>>            }
>>    
>> +        long dtracePid = dtraceProcess.pid();
>> +        Utils.tryWith("sudo", "kill", "-15", Long.toString(dtracePid));
>> +
>>            Collection<String> messages = Utils.destroy(dtraceProcess);
>>            if (!messages.isEmpty()) {
>>                throw new IllegalStateException(messages.toString());
>>
> 
> Because a few lines below, JMH calls Utils.destroy, which in turns calls java.lang.Process::destroy,
> which in turns calls java.lang.ProcessHandleImpl::destroy(), which in turn calls
> java.lang.ProcessHandleImpl::destroyProcess(/* force = */ false), which calls (I think)
> Java_java_lang_ProcessHandleImpl_destroy0 from ProcessHandleImpl_unix.c, which does deliver SIGTERM:
> 
> JNIEXPORT jboolean JNICALL
> Java_java_lang_ProcessHandleImpl_destroy0(JNIEnv *env,
>                                             jobject obj,
>                                             jlong jpid,
>                                             jlong startTime,
>                                             jboolean force) {
>       pid_t pid = (pid_t) jpid;
>       int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM; // <--- here
>       jlong start = Java_java_lang_ProcessHandleImpl_isAlive0(env, obj, jpid);
> 
>       if (start == startTime || start == 0 || startTime == 0) {
>           return (kill(pid, sig) < 0) ? JNI_FALSE : JNI_TRUE;
>       } else {
>           return JNI_FALSE;
>       }
> }
> 
> ...so if we actually deliver KILL not TERM on MacOS, that looks like a JDK bug?

Hold on. So if we call Process.destroy, then we also close all the streams at the same time?
   https://bugs.openjdk.java.net/browse/JDK-8216990

Whoa. So even the workaround above does not work reliably, as it races with the profiler process: if 
we are lucky, profiler would succeed in dumping the output after the first SIGTERM, until 
Process.destroy comes and closes everything. Hm.

-- 
Thanks,
-Aleksey



More information about the jmh-dev mailing list