Keep Glass attached through target-worker shutdown

Early Platform.exit detached JavaFX while queued macOS activation callbacks still called Java. Close the owned example before terminating its JVM, make shutdown idempotent, and reject late preview work. Add real startup-cancellation regressions and native crash-report checks.
This commit is contained in:
2026-11-12 15:03:51 +01:00
parent 886ce4a96f
commit 7b1d754320
10 changed files with 245 additions and 14 deletions
+49
View File
@@ -0,0 +1,49 @@
"""Keep a passing UI marker from hiding a target JVM's native fatal report."""
from pathlib import Path
import os
import subprocess
import time
class NativeCrashGuard:
def __init__(self, directory):
self.directory = Path(directory)
self.before = {p: p.stat().st_mtime_ns for p in self.directory.glob("hs_err_pid*.log")}
def check(self):
reports = [p for p in self.directory.glob("hs_err_pid*.log")
if self.before.get(p) != p.stat().st_mtime_ns]
if reports:
raise AssertionError("Native JVM crash reports: " + ", ".join(map(str, reports)))
def descendant_workers(owner):
rows = subprocess.check_output(["ps", "-axo", "pid=,ppid=,command="], text=True)
processes = {}
for line in rows.splitlines():
fields = line.strip().split(None, 2)
if len(fields) == 3:
processes[int(fields[0])] = (int(fields[1]), fields[2])
descendants = {owner}
while True:
found = {pid for pid, (parent, _) in processes.items() if parent in descendants}
if found <= descendants:
break
descendants |= found
return {pid for pid in descendants if pid in processes
and "de.neitzel.fxdesigner.target.WorkerMain" in processes[pid][1]}
def await_worker_exit(pids):
pending = set(pids)
deadline = time.monotonic() + 10
while pending and time.monotonic() < deadline:
for pid in tuple(pending):
try:
os.kill(pid, 0)
except ProcessLookupError:
pending.remove(pid)
if pending:
time.sleep(.05)
if pending:
raise AssertionError("Workers survived owner shutdown: " + str(sorted(pending)))