[DO NOT MERGE] Capture app startup diagnostics for Windows apps - #3062
Open
freakboy3742 wants to merge 3 commits into
Open
freakboy3742 wants to merge 3 commits into
freakboy3742 wants to merge 3 commits into
Conversation
A GUI app on Windows is built against the GUI subsystem, so it has no console attached, and its stdout/stderr never reach the pipe that Briefcase is streaming. As a result, an app that fails during interpreter or GUI toolkit startup produces no diagnostic output whatsoever; all Briefcase can report is the process exit code. This is the cause of the diagnostic dead end in beeware#2969: the failing PySide6 CI runs report "return code 1" with no other information, and a comparison against a *successful* run shows the same complete absence of app output, so the existing logs cannot distinguish a healthy app from a failing one. The automation bootstraps now record their progress through startup to a file nominated by BRIEFCASE_STARTUP_LOG, with faulthandler and an excepthook wired into the same file so that native crashes and unhandled exceptions are captured. If the app fails to run, Briefcase reports the contents of that file, identifying how far the app got before it died. Refs beeware#2969
The startup diagnostics show that a failing Windows app completes its entire lifecycle - every checkpoint fires, including the exit timer and the atexit hook - and still reports "return code 1". The app is not crashing, so the failure must occur at or after process exit. Three things are now reported when an app exits with a non-zero status: * the exit code the app reported in its own output, alongside the exit status of the process. Outside test mode, the value from the log filter is discarded and only popen.poll() is used, so a disagreement between the two is currently invisible. * the number of lines of app output seen while streaming, to confirm whether a GUI app's output reaches Briefcase at all. * whether the app was still running 3s after reporting its exit code. Subprocess.cleanup() also now reports when it terminates a process that is still running. On Windows, terminate() is TerminateProcess(handle, 1), so this is indistinguishable from the app itself exiting with status 1. Refs beeware#2969
Briefcase sees no app output at all from the PySide6 app under CI, in both passing and failing runs - but a GUI app's print() output *is* visible when the app is run interactively, so "GUI apps can't stream" is not the explanation. Why the output goes missing under CI is not yet understood, and it matters: if the output were arriving, the log filter would match the exit sentinel and report the app's own exit code, rather than falling back to the process exit status. The app now records the state of its stdout and stderr to the startup log, at interpreter start and again at the point the exit sentinels are printed. This distinguishes the possibilities: a None stream (making print() a silent no-op), a closed or erroring stream, or a stream that accepts the write successfully - which would mean the output is lost after the app hands it over. A raw os.write() to fd 1 is also attempted, to separate a problem in Python's stream setup from a problem with the pipe itself. Also corrects a comment that asserted Windows GUI apps can never stream output, which is untrue. Refs beeware#2969
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An attempt to diagnose the CI instabilities reported in #2969: the failing PySide6 CI runs report "return code 1" with no other information.
This PR adds progress logging to the automation bootstraps to a file nominated by BRIEFCASE_STARTUP_LOG, with faulthandler and an excepthook wired into the same file so that native crashes and unhandled exceptions are captured. If the app fails to run, Briefcase reports the contents of that file, identifying how far the app got before it died.
Refs #2969
PR Checklist:
Assisted-by: Claude Opus 5