[Opstart][P1] Tweede start verdwijnt stil: Windows zonder (of met hangend) primair venster, Linux zonder bestand #2679

Closed
opened 2026-10-31 09:47:39 +00:00 by brenno · 4 comments
Owner

Symptoom

De enkel-exemplaarbewaking uit #2627/#2656 kan een tweede start stil laten verdwijnen:

  • Windows, primair venster niet (meer) te vinden. Start of dubbelklik je OciDeck terwijl het eerste exemplaar nog opstart of nog afsluit, dan stopt het tweede proces zonder iets te tonen. Bij opstarten bestaat de mutex al maar is het venster nog niet gemarkeerd. Bij afsluiten is het venster weg, maar het proces loopt nog de begrensde stappen uit #2631 af (tot ~5 s) of wacht op een plugin-thread. Een meegegeven bestand gaat dan verloren. Blijft het eerste proces zonder venster hangen, dan start OciDeck tot een herstart of Taakbeheer helemaal niet meer. Dat is precies de klacht "start niet". #2627 noemde dit opstart/afsluit-venster expliciet als scenario.
  • Windows, primair proces hangt (UI-thread bezet). De tweede starter blijft dan onzichtbaar hangen in SendMessageW(WM_COPYDATA).
  • Linux, tweede start zonder bestand (menu, dock, .desktop). Het bestaande venster komt niet naar voren, er gebeurt zichtbaar niets. En omdat de kernel de verbinding al in de backlog accepteert, "slaagt" forwardToPrimary ook als de primaire hangt.

Oorzaak

  • windows/runner/main.cpp:103-118: bij ERROR_ALREADY_EXISTS geldt if (HWND primary = FindPrimaryInstanceWindow()) {…}, en daarna volgt altijd return EXIT_SUCCESS, ook als er geen venster gevonden is. kPrimaryInstanceProp wordt pas ná window.Create gezet (r. 136-141).
  • main.cpp:79: SendMessageW heeft geen time-out.
  • lib/services/single_instance.dart:110: if (paths.isEmpty) return; — er is geen "activeer"-signaal. forwardToPrimary (r. 59-80) wacht op geen antwoord.

Voorgestelde oplossing

  1. Windows, geen venster gevonden: een paar seconden pollen op FindPrimaryInstanceWindow() (bijv. 10× 300 ms). Is er dan nog niets, stop dan niet stil maar toon een MessageBoxW: "OciDeck is nog bezig met opstarten of afsluiten — Opnieuw proberen / Annuleren". Een alternatief: start als gewoon exemplaar door. Dat is sinds het herstel-lock per sessie (#2656) veilig. Schrijf in beide gevallen een logregel.
  2. Windows, hangende primaire: gebruik SendMessageTimeoutW(…, SMTO_ABORTIFHUNG | SMTO_BLOCK, 2000, …). Bij een time-out volgt dezelfde melding als in punt 1.
  3. Linux: stuur altijd een bericht, ook een leeg. Laat de primaire bij elk bericht het venster tonen en focussen (window.show(); window.focus();, zoals in configureNativeWindow, lib/platform/native_window_io.dart:22-23) en ok\n terugsturen. forwardToPrimary wacht daar hooguit 2 s op. Geen antwoord betekent dat de primaire hangt; volg dan dezelfde route als op Windows.

Wat overeind moet blijven

  • Het beamervenster (multi_window) gaat altijd door de mutex heen.
  • Het bestand van een tweede starter landt als tabblad in het eerste exemplaar (de toets uit #2627).
  • Een achtergebleven socket na een crash wordt nog steeds opgeruimd.

Toets

  • Dart: een lege start roept bij de primaire een activeer-handler aan. Een primaire die niet antwoordt, laat forwardToPrimary binnen de time-out false geven.
  • Windows-spiegel: start ocideck.exe binnen 1 s na het sluiten van het eerste venster. Er verschijnt een venster of een melding, nooit niets.

Gevonden bij codelezing tijdens de vervolginspectie van 31-10-2026.

## Symptoom De enkel-exemplaarbewaking uit #2627/#2656 kan een tweede start **stil laten verdwijnen**: - **Windows, primair venster niet (meer) te vinden.** Start of dubbelklik je OciDeck terwijl het eerste exemplaar nog **opstart** of nog **afsluit**, dan stopt het tweede proces zonder iets te tonen. Bij opstarten bestaat de mutex al maar is het venster nog niet gemarkeerd. Bij afsluiten is het venster weg, maar het proces loopt nog de begrensde stappen uit #2631 af (tot ~5 s) of wacht op een plugin-thread. Een meegegeven bestand gaat dan verloren. Blijft het eerste proces zonder venster hangen, dan start OciDeck tot een herstart of Taakbeheer helemaal niet meer. Dat is precies de klacht "start niet". #2627 noemde dit opstart/afsluit-venster expliciet als scenario. - **Windows, primair proces hangt** (UI-thread bezet). De tweede starter blijft dan onzichtbaar hangen in `SendMessageW(WM_COPYDATA)`. - **Linux, tweede start zonder bestand** (menu, dock, `.desktop`). Het bestaande venster komt niet naar voren, er gebeurt zichtbaar niets. En omdat de kernel de verbinding al in de backlog accepteert, "slaagt" `forwardToPrimary` ook als de primaire hangt. ## Oorzaak - `windows/runner/main.cpp:103-118`: bij `ERROR_ALREADY_EXISTS` geldt `if (HWND primary = FindPrimaryInstanceWindow()) {…}`, en daarna volgt altijd `return EXIT_SUCCESS`, ook als er geen venster gevonden is. `kPrimaryInstanceProp` wordt pas ná `window.Create` gezet (r. 136-141). - `main.cpp:79`: `SendMessageW` heeft geen time-out. - `lib/services/single_instance.dart:110`: `if (paths.isEmpty) return;` — er is geen "activeer"-signaal. `forwardToPrimary` (r. 59-80) wacht op geen antwoord. ## Voorgestelde oplossing 1. **Windows, geen venster gevonden:** een paar seconden pollen op `FindPrimaryInstanceWindow()` (bijv. 10× 300 ms). Is er dan nog niets, stop dan niet stil maar toon een `MessageBoxW`: "OciDeck is nog bezig met opstarten of afsluiten — Opnieuw proberen / Annuleren". Een alternatief: start als gewoon exemplaar door. Dat is sinds het herstel-lock per sessie (#2656) veilig. Schrijf in beide gevallen een logregel. 2. **Windows, hangende primaire:** gebruik `SendMessageTimeoutW(…, SMTO_ABORTIFHUNG | SMTO_BLOCK, 2000, …)`. Bij een time-out volgt dezelfde melding als in punt 1. 3. **Linux:** stuur altijd een bericht, ook een leeg. Laat de primaire bij elk bericht het venster tonen en focussen (`window.show(); window.focus();`, zoals in `configureNativeWindow`, `lib/platform/native_window_io.dart:22-23`) en `ok\n` terugsturen. `forwardToPrimary` wacht daar hooguit 2 s op. Geen antwoord betekent dat de primaire hangt; volg dan dezelfde route als op Windows. ## Wat overeind moet blijven - Het beamervenster (`multi_window`) gaat altijd door de mutex heen. - Het bestand van een tweede starter landt als tabblad in het eerste exemplaar (de toets uit #2627). - Een achtergebleven socket na een crash wordt nog steeds opgeruimd. ## Toets - Dart: een lege start roept bij de primaire een activeer-handler aan. Een primaire die niet antwoordt, laat `forwardToPrimary` binnen de time-out `false` geven. - Windows-spiegel: start `ocideck.exe` binnen 1 s na het sluiten van het eerste venster. Er verschijnt een venster of een melding, nooit niets. Gevonden bij codelezing tijdens de vervolginspectie van 31-10-2026.
Author
Owner

Opgepakt. Tak: fix/vervolginspectie-3110. Verwachte reikwijdte: de bestanden die in de oorzaak van dit issue staan, plus een regressietest.

Opgepakt. Tak: fix/vervolginspectie-3110. Verwachte reikwijdte: de bestanden die in de oorzaak van dit issue staan, plus een regressietest.
Author
Owner

Opgepakt. Tak: fix/vervolginspectie-3110. Verwachte reikwijdte: windows/runner/main.cpp, lib/services/single_instance.dart, lib/platform/native_window_io.dart.

Opgepakt. Tak: fix/vervolginspectie-3110. Verwachte reikwijdte: windows/runner/main.cpp, lib/services/single_instance.dart, lib/platform/native_window_io.dart.
Author
Owner

Staat op main in a6b4dc066 (dd8490b34). Een lege Linux-start activeert het bestaande venster; antwoordt dat niet, dan gaat de nieuwe start zelf verder en schrijft dat in het logboek. De Windows-vraag staat in windows/runner/main.cpp en is niet met een widgettest gedekt. Annuleren start geen tweede exemplaar.

Staat op main in a6b4dc066 (dd8490b34). Een lege Linux-start activeert het bestaande venster; antwoordt dat niet, dan gaat de nieuwe start zelf verder en schrijft dat in het logboek. De Windows-vraag staat in windows/runner/main.cpp en is niet met een widgettest gedekt. Annuleren start geen tweede exemplaar.
Author
Owner

Opgelost op main in a6b4dc066. De zin „een tweede start stil laten verdwijnen“ is gedekt door windows/runner/main.cpp (SendMessageTimeoutW en de melding opnieuw of annuleren) en lib/services/single_instance.dart (leeg activeerbericht, primaryDidNotAnswer). Niet meegenomen: de Windows-MessageBox draait niet onder flutter test. De Dart-toets dekt het Linux-protocol.

Opgelost op main in a6b4dc066. De zin „een tweede start stil laten verdwijnen“ is gedekt door windows/runner/main.cpp (SendMessageTimeoutW en de melding opnieuw of annuleren) en lib/services/single_instance.dart (leeg activeerbericht, primaryDidNotAnswer). Niet meegenomen: de Windows-MessageBox draait niet onder flutter test. De Dart-toets dekt het Linux-protocol.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#2679
No description provided.