Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8306758: com/sun/jdi/ConnectedVMs.java fails with "Non-zero debuggee exitValue: 143" #13848

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 24 additions & 4 deletions test/jdk/com/sun/jdi/ConnectedVMs.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
Expand Down Expand Up @@ -28,6 +28,7 @@
* VirtualMachineManager.connectedVirtualMachines()
* @author Robert Field
*
* @library /test/lib
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run compile -g InstTarg.java
* @run driver ConnectedVMs Kill
Expand All @@ -40,6 +41,8 @@
import com.sun.jdi.request.*;
import java.util.List;

import jdk.test.lib.Platform;

public class ConnectedVMs extends TestScaffold {
static int failCount = 0;;
static String passName;
Expand All @@ -62,6 +65,23 @@ public static void main(String args[]) throws Exception {
System.out.println("create " + passName);
}

@Override
protected boolean allowedExitValue(int exitValue) {
if (passName.equals("Kill")) {
// 143 is SIGTERM, which we expect to get when doing a Process.destroy(),
// unless we are on Windows, which will exit with a 1.
if (!Platform.isWindows()) {
return exitValue == 143;
} else {
return exitValue == 1;
}
} else if (passName.equals("exit()")) {
// This version of the test does an exit(1), so that's what we expect.
return exitValue == 1;
}
return super.allowedExitValue(exitValue);
}

void vms(int expected) {
List vms = Bootstrap.virtualMachineManager().
connectedVirtualMachines();
Expand All @@ -76,9 +96,9 @@ void vms(int expected) {
protected void runTests() throws Exception {
System.out.println("Testing " + passName);
vms(0);
startToMain("InstTarg");
ThreadReference thread = waitForVMStart();
StepEvent stepEvent = stepIntoLine(thread);
BreakpointEvent bp = startToMain("InstTarg");
waitForVMStart();
StepEvent stepEvent = stepIntoLine(bp.thread());
Comment on lines +99 to +101
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were needed for virtual thread support. startToMain("InstTarg") causes the debuggee to run until it it is suspended at a breakpoint in InstTarg.main(). waitForVMStart() will return right away since the VM has already started, and will return the main thread of the debuggee, but this is the thread running TestScaffold.main(), which started up InstTarg.main() in a virtual thread. If we single step in the main thread in this case, the single step is not in InstTarg.main() as it should be, but is instead in main thread, which is blocked in the join() call waiting for the virtual thread to complete. The single step resumes all threads, but can't complete until the virtual thread exits. So before the test ever gets to do the Process.destroy(), InstTarg.main() has already exited

Fortunately it was easy to find the proper thread to single step in, since the virtual thread is the BreakpointEvent thread.

vms(1);

// pick a way to die based on the input arg.
Expand Down
12 changes: 11 additions & 1 deletion test/jdk/com/sun/jdi/InstTarg.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023 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
Expand Down Expand Up @@ -29,6 +29,16 @@ public class InstTarg {

public static void main(String args[]) {
start();
// Sleep before exiting to allow disconnect efforts done on the JDI side to complete.
// Note that not sleeping long enough is for the most part harmless, but might render
// the testing insufficient because the debuggee will quickly exit naturally
// once the debuggee does the vm.resume(), rather than waiting for disconnect
// efforts to complete first.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

static void start() {
Expand Down
14 changes: 9 additions & 5 deletions test/jdk/com/sun/jdi/TestScaffold.java
Expand Up @@ -722,6 +722,12 @@ public synchronized ThreadReference waitForVMStart() {
return vmStartThread;
}

//
// Tests that expect an exitValue other than 0 will need to override this method.
protected boolean allowedExitValue(int exitValue) {
return exitValue == 0 || exitValue == 1;
}

public synchronized void waitForVMDisconnect() {
traceln("TS: waitForVMDisconnect");
while (!vmDisconnected) {
Expand All @@ -738,11 +744,9 @@ public synchronized void waitForVMDisconnect() {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int res = p.exitValue();
// Some tests purposefully exit with an exception, which produces exitValue
// 1, so we have to allow it also.
if (res != 0 && res != 1) {
throw new RuntimeException("Non-zero debuggee exitValue: " + res);
int exitValue = p.exitValue();
if (!allowedExitValue(exitValue)) {
throw new RuntimeException("Invalid debuggee exitValue: " + exitValue);
}

traceln("TS: waitForVMDisconnect: done");
Expand Down