Skip to content

fix: add 3s timeout to keychain init to prevent hang on Linux SSH sessions#16

Open
Slach wants to merge 2 commits intoportel-dev:mainfrom
Slach:fix/keyring-hang-without-display
Open

fix: add 3s timeout to keychain init to prevent hang on Linux SSH sessions#16
Slach wants to merge 2 commits intoportel-dev:mainfrom
Slach:fix/keyring-hang-without-display

Conversation

@Slach
Copy link
Copy Markdown
Contributor

@Slach Slach commented Mar 19, 2026

Problem

On Linux in SSH sessions without DISPLAY or WAYLAND_DISPLAY, ncp list and all other NCP commands hang forever with no output and no log entries — even with --debug.

Root cause: SecureCredentialStore.initializeKeychain() calls testEntry.setPassword('test') via @napi-rs/keyring (libsecret). When gnome-keyring-daemon is running but the vault is locked, libsecret issues a D-Bus call and waits indefinitely for a GUI unlock dialog that never appears in a headless environment. There is no timeout on this operation.

Reproduction:

# SSH into a Linux machine without display forwarding
ssh user@host
ncp list  # hangs forever, no output

Confirmed with:

echo "DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
# DISPLAY= WAYLAND_DISPLAY=

timeout 3 secret-tool store --label='ncp-test' service ncp-test account test <<< "testpassword"
# FAILED/TIMEOUT  ← keyring locked, no GUI to unlock it

Fix

Wrap the keychain test (setPassword / getPassword / deletePassword) in a Promise.race with a 3-second timeout. On timeout, the error is caught and the code falls back to the existing encrypted-file credential storage (~/.ncp/tokens/). All NCP functionality continues to work correctly in headless/SSH environments.

Test plan

  • ncp list in SSH session without DISPLAY no longer hangs (exits in <4s)
  • ncp list in a normal desktop session still uses OS keychain as before
  • Debug log shows: OS keychain unavailable, using encrypted file storage: Keychain test timed out after 3000ms

🤖 Generated with Claude Code

… display

On Linux in SSH sessions without DISPLAY/WAYLAND_DISPLAY, the gnome-keyring-daemon
may be running but locked. libsecret's D-Bus calls then wait indefinitely for a
GUI unlock dialog that never appears, causing `ncp list` and all other commands
to hang forever with no output.

Add a 3-second Promise.race timeout around the keychain test. On timeout the
code falls back to the existing encrypted-file credential storage, so all NCP
functionality continues to work correctly in headless/SSH environments.

Fixes: ncp list hanging in SSH sessions on Linux even with gnome-keyring running.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Slach
Copy link
Copy Markdown
Contributor Author

Slach commented Mar 19, 2026

As a workaround, I used echo -n 'password' | gnome-keyring-daemon --unlock

@napi-rs/keyring uses native N-API which runs synchronously on the Node.js
main thread. On Linux without DISPLAY/WAYLAND_DISPLAY (SSH/headless), the
gnome-keyring-daemon is running but locked — libsecret's D-Bus call blocks
the entire event loop waiting for a GUI unlock dialog that never appears.

Promise.race with setTimeout cannot help here because the native call holds
the event loop and setTimeout never fires.

Fix: check for Linux + no display before importing @napi-rs/keyring at all,
and fall back immediately to encrypted file storage.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Arul- Arul- self-assigned this Apr 6, 2026
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