Skip to content

installer: wait on _MSIExecute mutex instead of failing on 1618#9

Merged
rodchristiansen merged 2 commits into
mainfrom
fix/serialize-on-msi-mutex
Jun 23, 2026
Merged

installer: wait on _MSIExecute mutex instead of failing on 1618#9
rodchristiansen merged 2 commits into
mainfrom
fix/serialize-on-msi-mutex

Conversation

@rodchristiansen

Copy link
Copy Markdown
Contributor

Problem

During ESP, the Intune Management Extension and BootstrapMate both drive msiexec concurrently, so installs collide with 1618 ERROR_INSTALL_ALREADY_RUNNING. The old loop counted 1618 against the per-package retry budget and surfaced a [!] warning, so a long concurrent install could exhaust retries and fail a good package.

Fix

  • Add WaitForWindowsInstallerIdle(): before each msiexec launch, wait on the global Global_MSIExecute mutex until no other MSI transaction is mid-execution (best-effort; an unopenable mutex is treated as idle so a permissions quirk never blocks a bootstrap).
  • Treat any 1618 that still slips through as a scheduling wait, not a failure: log at debug, wait for idle, retry WITHOUT consuming the functional retry budget. Bounded at 30 collisions so a stuck installer can't loop forever.

Genuine failures (non-zero, non-1618) keep existing retry/fail behavior — this does not swallow real install errors.

Test

dotnet build BootstrapMate.csproj -c Release succeeds (0 errors).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves MSI installation robustness by serializing msiexec launches behind the global Global\_MSIExecute mutex and treating 1618 (ERROR_INSTALL_ALREADY_RUNNING) as a scheduling collision rather than a package failure, preventing retry budget exhaustion during concurrent installs (e.g., ESP/Intune).

Changes:

  • Added WaitForWindowsInstallerIdle() helper that polls Global\_MSIExecute before launching msiexec.
  • Updated MSI retry loop to wait/retry on 1618 without consuming the per-package retry budget, with a collision cap.
  • Adjusted logging and retry behavior to preserve existing handling for non-1618 failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Program.cs
Comment on lines +1250 to +1254
// Serialize behind any in-progress MSI transaction so we don't collide
// with 1618 ERROR_INSTALL_ALREADY_RUNNING in the first place. This is
// the "brute force" part: BootstrapMate waits its turn instead of failing.
WaitForWindowsInstallerIdle(installerIdleWaitSeconds);

Comment thread Program.cs
Comment on lines 1255 to +1257
using var process = Process.Start(startInfo);
if (process != null)
if (process == null) continue;

Comment thread Program.cs
Comment on lines +1284 to +1287
WriteLog($"MSI already running (1618) - waiting for the active installer to finish, then retrying (collision {collisions}, not counted as a failed attempt)");
WaitForWindowsInstallerIdle(installerIdleWaitSeconds);
attempt--; // do not count a scheduling collision against maxRetries
continue;
@rodchristiansen rodchristiansen merged commit 1d9f102 into main Jun 23, 2026
2 checks passed
@rodchristiansen rodchristiansen deleted the fix/serialize-on-msi-mutex branch June 23, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants