From c4e5d3f058e6aca21678d52189d07497b1895f92 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Sat, 22 Aug 2026 10:24:38 +1000 Subject: [PATCH] Treat an inaccessible tray mutex as no tray Both mutex probes caught only IOException, for the documented macOS case where opening a mutex that does not exist throws. Mutex.TryOpenExisting also documents UnauthorizedAccessException, for a mutex that does exist but is not accessible to this caller - the tray running under one account and the tests under another in the same session, which is ordinary on a shared or elevated desktop. "Not accessible" is not the same as "not running", but from inside the probe there is nothing to tell them apart with, and the answer that keeps a diff tool launching is the one to take. The consequence in DiffEngineTray is out of proportion to the cause: that probe is in a static constructor, so the exception becomes a TypeInitializationException and every later DiffRunner.Launch and AddDelete in the process throws it, for the life of the process. No test. The condition needs a mutex owned by another account, which cannot be arranged from inside the suite. --- src/DiffEngine/Tray/DiffEngineTray.cs | 7 +++++++ src/DiffEngine/Tray/TrayDetector.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/DiffEngine/Tray/DiffEngineTray.cs b/src/DiffEngine/Tray/DiffEngineTray.cs index 7a265016..8639b860 100644 --- a/src/DiffEngine/Tray/DiffEngineTray.cs +++ b/src/DiffEngine/Tray/DiffEngineTray.cs @@ -17,6 +17,13 @@ static DiffEngineTray() catch (IOException) { } + // A mutex that exists but is not accessible to this caller, which Mutex.TryOpenExisting + // documents: the tray under one account and the tests under another. Uncaught in a static + // constructor it is far worse than a wrong answer - the type never initialises, so every + // later DiffRunner.Launch and AddDelete in the process throws TypeInitializationException + catch (UnauthorizedAccessException) + { + } } public static bool IsRunning { get; internal set; } diff --git a/src/DiffEngine/Tray/TrayDetector.cs b/src/DiffEngine/Tray/TrayDetector.cs index 893e1c6c..d2ae506b 100644 --- a/src/DiffEngine/Tray/TrayDetector.cs +++ b/src/DiffEngine/Tray/TrayDetector.cs @@ -15,6 +15,13 @@ public static bool IsRunning() catch (IOException) { } + // Documented for a mutex that exists but cannot be opened by this caller: the tray running + // under one account and the tests under another in the same session. "Not accessible" is + // not "not running", but from here there is nothing to tell them apart with, and the + // answer that keeps a diff tool launching is the one to take + catch (UnauthorizedAccessException) + { + } return false; }