diff --git a/apps/desktop/lib/src/platform/smoke.dart b/apps/desktop/lib/src/platform/smoke.dart index 3438881..6f9b8ea 100644 --- a/apps/desktop/lib/src/platform/smoke.dart +++ b/apps/desktop/lib/src/platform/smoke.dart @@ -12,9 +12,14 @@ import 'ports/player_host.dart'; // in a session player with a video output through the media pipeline, // play a second and close the normal way ([shutDownApp]). Progress goes to // `STARSYNC_SMOKE_OUT` (one line per step: `start`, `opened render=`, -// `closing`, or `skip ` / `fail `), so the script can tell a -// runner that cannot show a window (skip) from a close that hangs or -// leaves a process behind (fail). +// `closing`, `quitting`, or `skip ` / `fail `), so the script can +// tell a runner that cannot show a window (skip) from a close that hangs or +// leaves a process behind, or a process that ends on its own (fail). It +// stays up [smokeUptime] first: a start that dies by itself (the 1.3.0 +// Windows exit timer) ends before `closing`. + +/// How long the smoke run keeps the app up before closing it. +const smokeUptime = Duration(seconds: 10); /// The smoke run's media, or null for a normal start. String? get smokeMedia { @@ -65,6 +70,9 @@ Future runSmoke(AppGraph graph, String media) async { } catch (e) { step('fail $e'); } + final wait = smokeUptime - sw.elapsed; + if (wait > Duration.zero) await Future.delayed(wait); step('closing'); - await shutDownApp(); + // Reached only through the app's own close (not a kill on the way). + await shutDownApp(beforeQuit: () async => step('quitting')); } diff --git a/apps/desktop/windows/runner/flutter_window.cpp b/apps/desktop/windows/runner/flutter_window.cpp index 6af950a..83ae4aa 100644 --- a/apps/desktop/windows/runner/flutter_window.cpp +++ b/apps/desktop/windows/runner/flutter_window.cpp @@ -80,7 +80,11 @@ bool FlutterWindow::OnCreate() { void FlutterWindow::OnDestroy() { // The engine and the plugins go now; the app released its players first. - ExitAfter(3000); + // Win32Window::Create runs this too, before there is an engine: only a + // real teardown may end the process (else every start dies at 3 s). + if (flutter_controller_) { + ExitAfter(3000); + } window_channel_ = nullptr; if (flutter_controller_) { flutter_controller_ = nullptr; diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 59746bf..63a7604 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -2293,7 +2293,9 @@ app kills itself (`Process.killPid`, no exit handlers; it only gets there if the close did not go through); the runners end the process 15 s after the first close request (Linux: a `delete-event` handler connected before window_manager's; Windows: the first `WM_CLOSE`), and Windows also 3 s -after the window is destroyed, while the engine and plugins go. +after the window is destroyed, while the engine and plugins go (only +with an engine: `Win32Window::Create` runs `OnDestroy` before the window +exists, and a timer armed there ended every start at 3 s). ## Logging diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index d119034..da305e5 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -210,10 +210,12 @@ updater tests, the release build and the close smoke run on that build `STARSYNC_SMOKE=` (a 5 s clip from ffmpeg, else a WAV the script writes) under its own profile (`STARSYNC_PROFILE=smoke`), opens the clip in a player with a video output through the media pipeline -(`platform/smoke.dart`), plays a second and closes the normal way; the -steps go to `STARSYNC_SMOKE_OUT` (`start`, `opened render=`, -`closing`, or `skip` / `fail` with why). It fails when the app does not -exit within 45 s or leaves a `starsync` process, skips with a warning +(`platform/smoke.dart`), plays it, stays up 10 s from its start and +closes the normal way; the steps go to `STARSYNC_SMOKE_OUT` (`start`, +`opened render=`, `closing`, `quitting` just before the +window closes, or `skip` / `fail` with why). It fails when the app ends +by itself before `closing` or never reaches `quitting`, does not exit +within 45 s or leaves a `starsync` process, skips with a warning when the runner cannot bring the app or its video output up, and prints the `smoke:`, `close:` and `mpv: render` lines of the app log. `tool/smoke_linux.sh` is the same on Linux (needs a display; after diff --git a/tool/smoke_linux.sh b/tool/smoke_linux.sh index 266df61..2c96a1a 100755 --- a/tool/smoke_linux.sh +++ b/tool/smoke_linux.sh @@ -34,6 +34,8 @@ grep -qx start "$OUT" 2>/dev/null || { [[ $exited == 1 ]] && { echo "skipped: th grep -q '^skip ' "$OUT" && { echo "skipped: $(grep '^skip ' "$OUT")"; exit 0; } grep -q '^fail ' "$OUT" && { echo "smoke failed: $(grep '^fail ' "$OUT")" >&2; exit 1; } grep -q '^opened ' "$OUT" || { echo "the media never opened" >&2; exit 1; } +grep -qx closing "$OUT" || { echo "the app ended on its own before closing" >&2; exit 1; } +grep -qx quitting "$OUT" || { echo "the close did not reach its end (killed on the way?)" >&2; exit 1; } [[ $exited == 1 ]] || { echo "the app did not close within $LIMIT s (P32)" >&2; exit 1; } [[ -z "$left" ]] || { echo "a starsync process was left behind (P32)" >&2; exit 1; } echo "smoke ok: opened and closed in $secs s, no process left" diff --git a/tool/smoke_windows.ps1 b/tool/smoke_windows.ps1 index b774fdb..ff7fe3b 100644 --- a/tool/smoke_windows.ps1 +++ b/tool/smoke_windows.ps1 @@ -64,6 +64,8 @@ if (-not ($lines -contains 'start')) { if ($lines | Where-Object { $_ -like 'skip *' }) { Write-Warning "skipped: $($lines -like 'skip *')"; exit 0 } if ($lines | Where-Object { $_ -like 'fail *' }) { Write-Error "smoke failed: $($lines -like 'fail *')"; exit 1 } if (-not ($lines | Where-Object { $_ -like 'opened *' })) { Write-Error 'the media never opened'; exit 1 } +if (-not ($lines -contains 'closing')) { Write-Error "the app ended on its own before closing (exit $($p.ExitCode))"; exit 1 } +if (-not ($lines -contains 'quitting')) { Write-Error 'the close did not reach its end (killed on the way?)'; exit 1 } if (-not $exited) { Write-Error "the app did not close within $Limit s (P32)"; exit 1 } if ($left) { Write-Error "a starsync process was left behind (P32)"; exit 1 } Write-Host "smoke ok: opened and closed in $secs s, no process left"