Skip to content

Commit d29217c

Browse files
committed
Set session socket into environment variable
While I was at it I added a CLI flag to override the default. I also swapped the default to --user-data-dir. The value is set on an environment variable so it can be used by the extension host similar to VSCODE_IPC_HOOK_CLI.
1 parent 56d10d8 commit d29217c

File tree

9 files changed

+61
-44
lines changed

9 files changed

+61
-44
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ Code v99.99.999
2424

2525
Code v1.79.2
2626

27+
### Fixed
28+
29+
- Fix being unable to launch multiple instances of code-server for different
30+
users.
31+
32+
### Added
33+
34+
- `--session-socket` CLI flag to configure the location of the session socket.
35+
By default it will be placed in `--user-data-dir`.
36+
2737
## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16
2838

2939
Code v1.79.2

patches/store-socket.diff

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
4040

4141
+ (async () => {
4242
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
43-
+ if (!socketPath) {
43+
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
44+
+ if (!socketPath || !codeServerSocketPath) {
4445
+ return;
4546
+ }
4647
+ const workspace = this._instaService.invokeFunction((accessor) => {
@@ -52,7 +53,6 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
5253
+ socketPath
5354
+ };
5455
+ const message = JSON.stringify({entry});
55-
+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock');
5656
+ await new Promise<void>((resolve, reject) => {
5757
+ const opts: _http.RequestOptions = {
5858
+ path: '/add-session',
@@ -109,12 +109,12 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
109109
+ onTerminate = (reason: string) => {
110110
+ extensionHostMain.terminate(reason);
111111
+
112+
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
112113
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
113-
+ if (!socketPath) {
114+
+ if (!socketPath || !codeServerSocketPath) {
114115
+ return;
115116
+ }
116117
+ const message = JSON.stringify({socketPath});
117-
+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock');
118118
+ const opts: _http.RequestOptions = {
119119
+ path: '/delete-session',
120120
+ socketPath: codeServerSocketPath,

src/node/app.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as util from "../common/util"
99
import { DefaultedArgs } from "./cli"
1010
import { disposer } from "./http"
1111
import { isNodeJSErrnoException } from "./util"
12-
import { DEFAULT_SOCKET_PATH, EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket"
12+
import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket"
1313
import { handleUpgrade } from "./wsRouter"
1414

1515
type SocketOptions = { socket: string; "socket-mode"?: string }
@@ -88,7 +88,7 @@ export const createApp = async (args: DefaultedArgs): Promise<App> => {
8888
handleUpgrade(wsRouter, server)
8989

9090
const editorSessionManager = new EditorSessionManager()
91-
const editorSessionManagerServer = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, editorSessionManager)
91+
const editorSessionManagerServer = await makeEditorSessionManagerServer(args["session-socket"], editorSessionManager)
9292
const disposeEditorSessionManagerServer = disposer(editorSessionManagerServer)
9393

9494
const dispose = async () => {

src/node/cli.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { load } from "js-yaml"
44
import * as os from "os"
55
import * as path from "path"
66
import { generateCertificate, generatePassword, humanPath, paths, splitOnFirstEquals } from "./util"
7-
import { DEFAULT_SOCKET_PATH, EditorSessionManagerClient } from "./vscodeSocket"
7+
import { EditorSessionManagerClient } from "./vscodeSocket"
88

99
export enum Feature {
1010
// No current experimental features!
@@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs {
5151
"disable-file-downloads"?: boolean
5252
"disable-workspace-trust"?: boolean
5353
"disable-getting-started-override"?: boolean
54+
"session-socket"?: string
5455
}
5556

5657
/**
@@ -160,6 +161,9 @@ export const options: Options<Required<UserProvidedArgs>> = {
160161
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
161162
"then notifies you once every week that a new release is available.",
162163
},
164+
"session-socket": {
165+
type: "string",
166+
},
163167
"disable-file-downloads": {
164168
type: "boolean",
165169
description:
@@ -459,6 +463,7 @@ export interface DefaultedArgs extends ConfigArgs {
459463
usingEnvHashedPassword: boolean
460464
"extensions-dir": string
461465
"user-data-dir": string
466+
"session-socket": string
462467
/* Positional arguments. */
463468
_: string[]
464469
}
@@ -479,6 +484,11 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
479484
args["extensions-dir"] = path.join(args["user-data-dir"], "extensions")
480485
}
481486

487+
if (!args["session-socket"]) {
488+
args["session-socket"] = path.join(args["user-data-dir"], "code-server-ipc.sock")
489+
}
490+
process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"]
491+
482492
// --verbose takes priority over --log and --log takes priority over the
483493
// environment variable.
484494
if (args.verbose) {
@@ -739,15 +749,15 @@ function bindAddrFromAllSources(...argsConfig: UserProvidedArgs[]): Addr {
739749
* existing instance. The arguments here should be the arguments the user
740750
* explicitly passed on the command line, *NOT DEFAULTS* or the configuration.
741751
*/
742-
export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Promise<string | undefined> => {
752+
export const shouldOpenInExistingInstance = async (args: UserProvidedArgs, sessionSocket: string): Promise<string | undefined> => {
743753
// Always use the existing instance if we're running from VS Code's terminal.
744754
if (process.env.VSCODE_IPC_HOOK_CLI) {
745755
logger.debug("Found VSCODE_IPC_HOOK_CLI")
746756
return process.env.VSCODE_IPC_HOOK_CLI
747757
}
748758

749759
const paths = getResolvedPathsFromArgs(args)
750-
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
760+
const client = new EditorSessionManagerClient(sessionSocket)
751761

752762
// If we can't connect to the socket then there's no existing instance.
753763
if (!(await client.canConnect())) {

src/node/entry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ async function entry(): Promise<void> {
5151
return runCodeCli(args)
5252
}
5353

54-
const socketPath = await shouldOpenInExistingInstance(cliArgs)
54+
const socketPath = await shouldOpenInExistingInstance(cliArgs, args["session-socket"])
5555
if (socketPath) {
5656
logger.debug("Trying to open in existing instance")
5757
return openInExistingInstance(args, socketPath)

src/node/vscodeSocket.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import * as http from "http"
44
import * as path from "path"
55
import { HttpCode } from "../common/http"
66
import { listen } from "./app"
7-
import { canConnect, paths } from "./util"
8-
9-
// Socket path of the daemonized code-server instance.
10-
export const DEFAULT_SOCKET_PATH = path.join(paths.data, `code-server-ipc.sock`)
7+
import { canConnect } from "./util"
118

129
export interface EditorSessionEntry {
1310
workspace: {

test/unit/node/cli.test.ts

+29-22
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
import { shouldSpawnCliProcess } from "../../../src/node/main"
1919
import { generatePassword, paths } from "../../../src/node/util"
2020
import {
21-
DEFAULT_SOCKET_PATH,
2221
EditorSessionManager,
2322
EditorSessionManagerClient,
2423
makeEditorSessionManagerServer,
@@ -37,6 +36,7 @@ const defaults = {
3736
usingEnvHashedPassword: false,
3837
"extensions-dir": path.join(paths.data, "extensions"),
3938
"user-data-dir": paths.data,
39+
"session-socket": path.join(paths.data, "code-server-ipc.sock"),
4040
_: [],
4141
}
4242

@@ -103,6 +103,8 @@ describe("parser", () => {
103103

104104
"--disable-getting-started-override",
105105

106+
["--session-socket", "/tmp/override-code-server-ipc-socket"],
107+
106108
["--host", "0.0.0.0"],
107109
"4",
108110
"--",
@@ -136,6 +138,7 @@ describe("parser", () => {
136138
"welcome-text": "welcome to code",
137139
version: true,
138140
"bind-addr": "192.169.0.1:8080",
141+
"session-socket": "/tmp/override-code-server-ipc-socket",
139142
})
140143
})
141144

@@ -504,22 +507,23 @@ describe("cli", () => {
504507
it("should use existing if inside code-server", async () => {
505508
process.env.VSCODE_IPC_HOOK_CLI = "test"
506509
const args: UserProvidedArgs = {}
507-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test")
510+
expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test")
508511

509512
args.port = 8081
510513
args._ = ["./file"]
511-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test")
514+
expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test")
512515
})
513516

514517
it("should use existing if --reuse-window is set", async () => {
515-
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
518+
const sessionSocket = path.join(tmpDirPath, "session-socket")
519+
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
516520

517521
const args: UserProvidedArgs = {}
518522
args["reuse-window"] = true
519-
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined)
523+
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(undefined)
520524

521525
const socketPath = path.join(tmpDirPath, "socket")
522-
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
526+
const client = new EditorSessionManagerClient(sessionSocket)
523527
await client.addSession({
524528
entry: {
525529
workspace: {
@@ -537,24 +541,25 @@ describe("cli", () => {
537541
})
538542
const vscodeSockets = listenOn(socketPath)
539543

540-
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath)
544+
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath)
541545

542546
args.port = 8081
543-
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath)
547+
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath)
544548

545549
server.close()
546550
vscodeSockets.close()
547551
})
548552

549553
it("should use existing if --new-window is set", async () => {
550-
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
554+
const sessionSocket = path.join(tmpDirPath, "session-socket")
555+
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
551556

552557
const args: UserProvidedArgs = {}
553558
args["new-window"] = true
554-
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined)
559+
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(undefined)
555560

556561
const socketPath = path.join(tmpDirPath, "socket")
557-
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
562+
const client = new EditorSessionManagerClient(sessionSocket)
558563
await client.addSession({
559564
entry: {
560565
workspace: {
@@ -572,25 +577,26 @@ describe("cli", () => {
572577
})
573578
const vscodeSockets = listenOn(socketPath)
574579

575-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
580+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
576581

577582
args.port = 8081
578-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
583+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
579584

580585
server.close()
581586
vscodeSockets.close()
582587
})
583588

584589
it("should use existing if no unrelated flags are set, has positional, and socket is active", async () => {
585-
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
590+
const sessionSocket = path.join(tmpDirPath, "session-socket")
591+
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
586592

587593
const args: UserProvidedArgs = {}
588-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
594+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
589595

590596
args._ = ["./file"]
591-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
597+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
592598

593-
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
599+
const client = new EditorSessionManagerClient(sessionSocket)
594600
const socketPath = path.join(tmpDirPath, "socket")
595601
await client.addSession({
596602
entry: {
@@ -609,18 +615,19 @@ describe("cli", () => {
609615
})
610616
const vscodeSockets = listenOn(socketPath)
611617

612-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
618+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
613619

614620
args.port = 8081
615-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
621+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
616622

617623
server.close()
618624
vscodeSockets.close()
619625
})
620626

621627
it("should prefer matching sessions for only the first path", async () => {
622-
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
623-
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
628+
const sessionSocket = path.join(tmpDirPath, "session-socket")
629+
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
630+
const client = new EditorSessionManagerClient(sessionSocket)
624631
await client.addSession({
625632
entry: {
626633
workspace: {
@@ -655,7 +662,7 @@ describe("cli", () => {
655662

656663
const args: UserProvidedArgs = {}
657664
args._ = ["/aaa/file", "/bbb/file"]
658-
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.sock`)
665+
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.`)
659666

660667
server.close()
661668
})

test/unit/node/plugin.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ describe("plugin", () => {
4343
usingEnvHashedPassword: false,
4444
"extensions-dir": "",
4545
"user-data-dir": "",
46+
"session-socket": "",
4647
}
4748
next()
4849
}

test/unit/node/vscodeSocket.test.ts

-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
import { logger } from "@coder/logger"
22
import * as app from "../../../src/node/app"
3-
import { paths } from "../../../src/node/util"
43
import {
5-
DEFAULT_SOCKET_PATH,
64
EditorSessionManager,
75
makeEditorSessionManagerServer,
86
} from "../../../src/node/vscodeSocket"
97
import { clean, tmpdir, listenOn, mockLogger } from "../../utils/helpers"
108

11-
describe("DEFAULT_SOCKET_PATH", () => {
12-
it("should be a unique path per user", () => {
13-
expect(DEFAULT_SOCKET_PATH.startsWith(paths.data)).toBe(true)
14-
})
15-
})
16-
179
describe("makeEditorSessionManagerServer", () => {
1810
let tmpDirPath: string
1911

0 commit comments

Comments
 (0)