@Override
		public void close() throws Exception {
			Msg.info(this, "Cleaning up gdb");
			try {
				try {
					RemoteAsyncResult asyncQuit = executeAsync("quit");
					try {
						asyncQuit.get(QUIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
					}
					catch (TimeoutException e) {
						/**
						 * This seems like a bug in gdb. AFAICT, it's a rehash or regression of
						 * https://sourceware.org/bugzilla/show_bug.cgi?id=17247. If I attach to the
						 * hung gdb, I get a similar stack trace, but with Python frames on the
						 * stack. The workaround given in the comments works here, too. I hesitate
						 * to point fingers, though, because I'm testing with a modern gdb-13.1
						 * compiled from source on a rather un-modern distro.
						 */
						Msg.warn(this, "gdb hung on quit. Sending SIGCONT.");
						Runtime.getRuntime().exec("kill -SIGCONT %d".formatted(exec.gdb.pid()));
						asyncQuit.get(QUIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
					}
				}
				catch (TraceRmiError e) {
					// expected
				}
				catch (ExecutionException e) {
					if (!(e.getCause() instanceof TraceRmiError)) {
						throw e;
					}
				}
				GdbResult r = exec.future.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
				r.handle();
				waitForPass(() -> assertTrue(connection.isClosed()));
			}
			finally {
				exec.gdb.destroyForcibly();
			}
		}
Some snapshot likely to exceed the latest
Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/gdb/rmi/AbstractGdbTraceRmiTest.java