From b5a9ef80e73b165dfd0d0630623449c039889293 Mon Sep 17 00:00:00 2001 From: Sean Lee Date: Wed, 21 Jun 2023 14:39:25 -0400 Subject: [PATCH] Use unique socket per user for managing editor sessions (#6278) Also warn if editor session manager socket cannot be created rather than failing. --- src/node/main.ts | 4 ++- src/node/vscodeSocket.ts | 11 ++++--- test/unit/node/vscodeSocket.test.ts | 49 +++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/node/main.ts b/src/node/main.ts index 5af1f5c6a..f4733b109 100644 --- a/src/node/main.ts +++ b/src/node/main.ts @@ -126,7 +126,9 @@ export const runCodeServer = async ( logger.info(`Using config file ${humanPath(os.homedir(), args.config)}`) logger.info(`${protocol.toUpperCase()} server listening on ${serverAddress.toString()}`) - logger.info(`Session server listening on ${sessionServerAddress?.toString()}`) + if (sessionServerAddress) { + logger.info(`Session server listening on ${sessionServerAddress.toString()}`) + } if (args.auth === AuthType.Password) { logger.info(" - Authentication is enabled") diff --git a/src/node/vscodeSocket.ts b/src/node/vscodeSocket.ts index 1bdb895f8..8dd75a840 100644 --- a/src/node/vscodeSocket.ts +++ b/src/node/vscodeSocket.ts @@ -1,14 +1,13 @@ import { logger } from "@coder/logger" import express from "express" import * as http from "http" -import * as os from "os" import * as path from "path" import { HttpCode } from "../common/http" import { listen } from "./app" -import { canConnect } from "./util" +import { canConnect, paths } from "./util" // Socket path of the daemonized code-server instance. -export const DEFAULT_SOCKET_PATH = path.join(os.tmpdir(), "code-server-ipc.sock") +export const DEFAULT_SOCKET_PATH = path.join(paths.data, `code-server-ipc.sock`) export interface EditorSessionEntry { workspace: { @@ -78,7 +77,11 @@ export async function makeEditorSessionManagerServer( }) const server = http.createServer(router) - await listen(server, { socket: codeServerSocketPath }) + try { + await listen(server, { socket: codeServerSocketPath }) + } catch (e) { + logger.warn(`Could not create socket at ${codeServerSocketPath}`) + } return server } diff --git a/test/unit/node/vscodeSocket.test.ts b/test/unit/node/vscodeSocket.test.ts index 7c5999415..cd84d6ba2 100644 --- a/test/unit/node/vscodeSocket.test.ts +++ b/test/unit/node/vscodeSocket.test.ts @@ -1,5 +1,50 @@ -import { EditorSessionManager } from "../../../src/node/vscodeSocket" -import { clean, tmpdir, listenOn } from "../../utils/helpers" +import { logger } from "@coder/logger" +import * as app from "../../../src/node/app" +import { paths } from "../../../src/node/util" +import { + DEFAULT_SOCKET_PATH, + EditorSessionManager, + makeEditorSessionManagerServer, +} from "../../../src/node/vscodeSocket" +import { clean, tmpdir, listenOn, mockLogger } from "../../utils/helpers" + +describe("DEFAULT_SOCKET_PATH", () => { + it("should be a unique path per user", () => { + expect(DEFAULT_SOCKET_PATH.startsWith(paths.data)).toBe(true) + }) +}) + +describe("makeEditorSessionManagerServer", () => { + let tmpDirPath: string + + const testName = "mesms" + + beforeAll(async () => { + jest.clearAllMocks() + mockLogger() + await clean(testName) + }) + + afterAll(() => { + jest.resetModules() + }) + + beforeEach(async () => { + tmpDirPath = await tmpdir(testName) + }) + + it("warns if socket cannot be created", async () => { + jest.spyOn(app, "listen").mockImplementation(() => { + throw new Error() + }) + const server = await makeEditorSessionManagerServer( + `${tmpDirPath}/code-server-ipc.sock`, + new EditorSessionManager(), + ) + expect(logger.warn).toHaveBeenCalledWith(`Could not create socket at ${tmpDirPath}/code-server-ipc.sock`) + server.close() + }) +}) describe("EditorSessionManager", () => { let tmpDirPath: string