Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/lib/actions/uninstall/run-plan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,4 +619,48 @@ describe("uninstall run plan", () => {
"Destroyed gateway 'nemoclaw' skipped",
);
});

it("#3516: kills the orphan openshell-gateway host process during uninstall", () => {
// When the host glibc satisfies the gateway requirement, NemoClaw spawns
// /usr/local/bin/openshell-gateway directly without a container wrapper
// (see src/lib/onboard/docker-driver-gateway-launch.ts shouldUseContainerizedGateway).
// `openshell gateway destroy` does not terminate this host-process variant,
// so the process keeps binding port 8080 after uninstall. Uninstall must
// pgrep for the binary and SIGTERM/SIGKILL any survivors.
const logs: string[] = [];
const killed: number[] = [];
const result = runUninstallPlan(
{ assumeYes: true, deleteModels: false, keepOpenShell: true },
{
commandExists: () => true,
env: { HOME: "/home/test", LOGNAME: "testuser" } as NodeJS.ProcessEnv,
existsSync: () => false,
isTty: false,
kill: (pid) => {
killed.push(pid);
return true;
},
log: (line) => logs.push(line),
rmSync: vi.fn(),
run: (command, args) => {
if (
command === "pgrep" &&
args[0] === "-f" &&
typeof args[1] === "string" &&
args[1].includes("openshell-gateway")
) {
return ok("8888\n");
}
if (args[0] === "-f") return ok("");
if (args[0] === "-c") return ok("/fake/bin/tool\n");
return ok();
},
runDocker: () => ok(""),
},
);

expect(result.exitCode).toBe(0);
expect(killed).toContain(8888);
expect(logs).toContain("Stopped openshell-gateway host process 8888");
});
});
1 change: 1 addition & 0 deletions src/lib/actions/uninstall/run-plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ function executePlan(plan: UninstallPlan, paths: UninstallPaths, options: Uninst
commandExists: runtime.commandExists,
});
stopOrphanedOpenShell(runtime);
stopMatchingPids("/openshell-gateway( |$)", runtime, "openshell-gateway host process");
stopOllamaAuthProxy(paths, runtime);
} else if (step.name === "OpenShell resources") {
removeOpenShellResources(options, runtime);
Expand Down
Loading