Skip to content

fix(session): wait for a losing logout teardown before re-creating its profile - #999

Merged
rmyndharis merged 1 commit into
mainfrom
fix/994-teardown-race-fencing
Jul 29, 2026
Merged

fix(session): wait for a losing logout teardown before re-creating its profile#999
rmyndharis merged 1 commit into
mainfrom
fix/994-teardown-race-fencing

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

Description

Fixes #994 (found reviewing #984; the race predates that PR but only becomes destructive with logout() in the mix).

teardownEngineSafely races an engine teardown against a 10s deadline via Promise.race, but the losing promise keeps running. For disconnect()/forceDestroy() that's benign — they never touch disk. logout() is the first teardown that deletes on-disk state (wwjs LocalAuth.logout()fs.rm of <dataPath>/session-<id>; Baileys clearAuthState()authDir/sessionId), and both are deterministic paths a subsequent start() re-creates: a pupBrowser.close() wedged past the deadline could land that rm on credentials written by a fresh pairing.

The change:

  • Track losing logout teardowns — the raw teardown promise (not the deadline-raced one) is registered in a pendingTeardowns map, self-removing on settlement with an identity check so a newer teardown's entry isn't evicted by an older one settling. Only 'logout' is tracked; the other teardown labels never touch disk.
  • Fence the disk-touching pathsstart() waits (bounded, 10s) for a pending teardown to settle before initializeEngine writes the fresh profile; delete() does the same before purgeSessionData. If the teardown is still wedged past the bound, the operator is not blocked indefinitely — the stale rm sits behind the wedge — and that residual window is logged (pending_teardown_wait_exhausted).

Two new service tests with fake timers: start() creates no engine while a losing logout teardown is pending and proceeds once it settles (entry self-removes); and start() proceeds after the bounded wait when the teardown never settles.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • Tests added/updated
  • Documentation updated
  • Lint passes
  • Self-reviewed

Related Issues

Closes #994

…s profile

teardownEngineSafely races a teardown against a 10s deadline, but the
losing promise keeps running — and logout()'s ends in an fs.rm of the
session's on-disk profile, the same deterministic path a later start()
re-creates. A pupBrowser.close() wedged past the deadline could land
that rm on credentials written by a subsequent pairing.

Losing logout() teardowns are now registered in a pendingTeardowns map
(self-removing on settlement), and start()/delete() wait (bounded) for
them before touching the profile path. A teardown still wedged past the
bound no longer blocks the operator; that residual window is logged.

Closes #994
@rmyndharis
rmyndharis merged commit 4933316 into main Jul 29, 2026
14 checks passed
@rmyndharis
rmyndharis deleted the fix/994-teardown-race-fencing branch July 29, 2026 10:33
rmyndharis added a commit that referenced this pull request Jul 29, 2026
…the deadline race (#1001)

PR #999 added two teardown-resilience tests that drive logout() with a
promise hung past the 10s deadline, then await the call assuming it
resolves. PR #997 (which landed first) made logout() throw
BadGatewayException whenever the unlink is unconfirmed — exactly the
outcome of a lost deadline race — so both tests have failed on main since
#999 merged on top of it.

The production behaviour from #997 is correct and already asserted
explicitly (logout() rejects with 502 when the unlink is unconfirmed, but
the local teardown still completes). This updates the two #999 tests to
expect that rejection, while preserving what they actually exercise: the
losing promise stays registered in pendingTeardowns and start() still
waits for it (bounded) before re-creating the profile.
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.

[Bug]: teardownEngineSafely's 10s deadline doesn't cancel the losing promise — a wedged logout can delete a freshly re-paired profile

1 participant