Skip to content

No timeout on startup-script preflight (a hung startup script wedges pool creation indefinitely) #85

Description

@aesslinger

Summary

src/client.rs::preflight_startup_script runs the user-configured startup script on a throwaway connection with no timeout. The built-in driver wraps the same preflight in a 30-second tokio::time::timeout. A broken script that blocks (or a stalled host) hangs pool creation — and therefore every metadata/query RPC — indefinitely.

Builtin behavior (upstream main)

src-tauri/src/pool_manager.rs:65:

/// The PostgreSQL startup-script preflight opens a real network connection, so
/// bound it the same way as SQLite: a broken script or a stalled host must
/// never wedge pool creation indefinitely.
const POSTGRES_STARTUP_SCRIPT_TIMEOUT_MS: u64 = 30_000;

…and at line 991, the preflight is wrapped:

let timeout = Duration::from_millis(POSTGRES_STARTUP_SCRIPT_TIMEOUT_MS);
tokio::time::timeout(timeout, run_postgres_startup_script(&cfg, tls_connector.clone(), &script))
    .await
    .map_err(|_| format!("Timed out running PostgreSQL startup script after {} ms", timeout.as_millis()))?;

Plugin behavior (this repo)

src/client.rs:452preflight_startup_script runs tx.batch_execute(script) directly with no timeout wrapper. There are zero tokio::time::timeout calls anywhere in src/. The script's BEGIN/batch_execute/ROLLBACK sequence runs until it finishes or the TCP connection dies; a script that blocks (e.g. an advisory lock, a slow function, a pg_sleep) hangs the preflight, which runs before build_pool returns, so the entire connection is unusable until then.

Impact

  • Severity: Medium. Requires a startup script configured and a script/host that stalls. Uncommon, but the builtin explicitly added the guard with a comment saying "a broken script or a stalled host must never wedge pool creation indefinitely" — this is a parity regression on a deliberate robustness guard.
  • The error message also differs: the builtin says "Timed out running PostgreSQL startup script after 30000 ms" (clear cause); the plugin hangs with no feedback.

Fix

Wrap the preflight body in tokio::time::timeout(Duration::from_millis(30_000), …) and map the elapsed error to the same "Timed out running PostgreSQL startup script after 30000 ms" message. Define POSTGRES_STARTUP_SCRIPT_TIMEOUT_MS to match the builtin. Add a unit/integration test exercising the timeout (a pg_sleep(35) startup script should fail with the timeout message, not hang) — per repo TDD guidance, prove the divergence first.

Related

  • Builtin reference: TabularisDB/tabularis pool_manager.rs:65 + :991.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcapability-gapA builtin-only feature this plugin doesn't yet support

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions