NationalSecurityAgency/ghidra · error · IOException

Error shutting down postgres server process

Error message

Error shutting down postgres server process

What it means

Thrown by stopCommand() when `pg_ctl stop [-m fast]` returns non-zero. BSim treats a non-zero exit as a failure to shut the server down; the postgres error detail is not surfaced.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java:1065

	 * Stop the running PostgreSQL processes on the local host. No authentication is required to shutdown
	 * the server.  User must be the process owner.
	 * @throws IOException if postgres cannot be discovered or stopped
	 * @throws InterruptedException if the stop command is interrupted
	 */
	private void stopCommand() throws IOException, InterruptedException {
		discoverPostgresInstall();
		List<String> command = new ArrayList<String>();
		command.add(postgresControl.getAbsolutePath());
		command.add("stop");
		command.add("-D");
		command.add(dataDirectory.getAbsolutePath());
		if (forceShutdown) {
			command.add("-m");
			command.add("fast");		// Does not wait for clients to disconnect, all active transactions rolled back
		}
		int res = runCommand(null, command, loadLibraryVar, loadLibraryValue);
		if (res != 0) {
			throw new IOException("Error shutting down postgres server process");
		}
		System.out.println("Server shutdown complete");
	}

	/**
	 * Retrieve the status of a PostgreSQL server.
	 * @throws IOException if server status can not be retrieved
	 * @throws InterruptedException if the status command is interrupted
	 */
	private void statusCommand() throws IOException, InterruptedException {
		discoverPostgresInstall();
		List<String> command = new ArrayList<String>();
		command.add(postgresControl.getAbsolutePath());
		command.add("status");
		command.add("-D");
		command.add(dataDirectory.getAbsolutePath());
		int res = runCommand(null, command, loadLibraryVar, loadLibraryValue);
		if (res == 0) {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Check whether postgres is actually running: `bsim_ctl status <dataDir>` or `pg_ctl status`.
  2. Remove a stale postmaster.pid if no process holds the port.
  3. Run bsim_ctl as the same OS user that owns the data directory.
  4. Retry with `--force` (maps to `pg_ctl stop -m fast`).
  5. Inspect postgres logs if the process exists but won't stop.
Defensive patterns

Strategy: try-catch

Validate before calling

// Only attempt stop if status indicates running.
int rc = runPgCtl("status", dataDir);
if (rc == 3) {
    return; // already down; skip stop to avoid the error
}

Type guard

public boolean serverLikelyRunning(File dataDir) {
    return new File(dataDir, "postmaster.pid").isFile();
}

Try / catch

try {
    bsimControl.stop(args);
} catch (IOException e) {
    if ("Error shutting down postgres server process".equals(e.getMessage())) {
        // check status; if already down, treat as success; else escalate.
        int rc = runPgCtl("status", dataDir);
        if (rc == 3) return;
        throw new UserFacingException("pg_ctl stop failed; server still up", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Running `bsim_ctl stop <dataDir>` (optionally `--force`) and the postgres stop command fails.

Common situations: Server already stopped or not running; stale postmaster.pid; insufficient privileges to signal the postmaster; data directory path mismatch; shutdown blocked and -m fast still timed out.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/c8c78614b5f869a2. Report an issue: GitHub.