Skip to content

Commit 30620ab

Browse files
committed
Reset connect timeout after connecting
1 parent 7b8e0c7 commit 30620ab

File tree

1 file changed

+66
-27
lines changed

1 file changed

+66
-27
lines changed

src/remote.ts

+66-27
Original file line numberDiff line numberDiff line change
@@ -265,43 +265,62 @@ export class Remote {
265265
agent = matchingAgents[0]
266266
}
267267

268-
let remotePlatforms = this.vscodeProposed.workspace
268+
const hostname = authorityParts[1]
269+
const remotePlatforms = this.vscodeProposed.workspace
269270
.getConfiguration()
270-
.get<Record<string, string>>("remote.SSH.remotePlatform")
271-
remotePlatforms = {
272-
...remotePlatforms,
273-
[`${authorityParts[1]}`]: agent.operating_system,
274-
}
275-
276-
// VS Code ignores the connect timeout in the SSH config and uses a default
277-
// of 15 seconds, which can be too short in the case where we wait for
278-
// startup scripts. For now we hardcode a longer value.
279-
// If microsoft/vscode-remote-release#8519 is resolved we can remove this.
280-
const connectTimeout = 1800
281-
271+
.get<Record<string, string>>("remote.SSH.remotePlatform", {})
272+
const connTimeout = this.vscodeProposed.workspace.getConfiguration().get<number | undefined>("remote.SSH.connectTimeout")
273+
274+
// We have to directly munge the settings file with jsonc because trying to
275+
// update properly through the extension API hangs indefinitely. Possibly
276+
// VS Code is trying to update configuration on the remote, which cannot
277+
// connect until we finish here leading to a deadlock. We need to update it
278+
// locally, anyway, and it does not seem possible to force that via API.
282279
let settingsContent = "{}"
283280
try {
284281
settingsContent = await fs.readFile(this.storage.getUserSettingsPath(), "utf8")
285282
} catch (ex) {
286283
// Ignore! It's probably because the file doesn't exist.
287284
}
288285

289-
settingsContent = jsonc.applyEdits(
290-
settingsContent,
291-
jsonc.modify(settingsContent, ["remote.SSH.remotePlatform"], remotePlatforms, {}),
292-
)
286+
// Add the remote platform for this host to bypass a step where VS Code asks
287+
// the user for the platform.
288+
let mungedPlatforms = false
289+
if (!remotePlatforms[hostname] || remotePlatforms[hostname] !== agent.operating_system) {
290+
remotePlatforms[hostname] = agent.operating_system
291+
settingsContent = jsonc.applyEdits(
292+
settingsContent,
293+
jsonc.modify(settingsContent, ["remote.SSH.remotePlatform"], remotePlatforms, {}),
294+
)
295+
mungedPlatforms = true
296+
}
293297

294-
settingsContent = jsonc.applyEdits(
295-
settingsContent,
296-
jsonc.modify(settingsContent, ["remote.SSH.connectTimeout"], connectTimeout, {}),
297-
)
298+
// VS Code ignores the connect timeout in the SSH config and uses a default
299+
// of 15 seconds, which can be too short in the case where we wait for
300+
// startup scripts. For now we hardcode a longer value. Because this is
301+
// potentially overwriting user configuration, it feels a bit sketchy. If
302+
// microsoft/vscode-remote-release#8519 is resolved we can remove this but
303+
// for now to mitigate the sketchiness we will reset it after connecting.
304+
const minConnTimeout = 1800
305+
let mungedConnTimeout = false
306+
if (!connTimeout || connTimeout < minConnTimeout) {
307+
settingsContent = jsonc.applyEdits(
308+
settingsContent,
309+
jsonc.modify(settingsContent, ["remote.SSH.connectTimeout"], minConnTimeout, {}),
310+
)
311+
mungedConnTimeout = true
312+
}
298313

299-
try {
300-
await fs.writeFile(this.storage.getUserSettingsPath(), settingsContent)
301-
} catch (ex) {
302-
// The user will just be prompted instead, which is fine!
303-
// If a user's settings.json is read-only, then we can't write to it.
304-
// This is the case when using home-manager on NixOS.
314+
if (mungedPlatforms || mungedConnTimeout) {
315+
try {
316+
await fs.writeFile(this.storage.getUserSettingsPath(), settingsContent)
317+
} catch (ex) {
318+
// This could be because the user's settings.json is read-only. This is
319+
// the case when using home-manager on NixOS, for example. Failure to
320+
// write here is not necessarily catastrophic since the user will be
321+
// asked for the platform and the default timeout might be sufficient.
322+
mungedPlatforms = mungedConnTimeout = false
323+
}
305324
}
306325

307326
const workspaceUpdate = new vscode.EventEmitter<Workspace>()
@@ -445,6 +464,26 @@ export class Remote {
445464
await this.updateSSHConfig(authorityParts[1], hasCoderLogs)
446465

447466
this.findSSHProcessID().then((pid) => {
467+
// Once the SSH process has spawned we can reset the timeout.
468+
if (mungedConnTimeout) {
469+
// Re-read settings in case they changed.
470+
fs.readFile(this.storage.getUserSettingsPath(), "utf8").then(async (rawSettings) => {
471+
try {
472+
await fs.writeFile(
473+
this.storage.getUserSettingsPath(),
474+
jsonc.applyEdits(
475+
rawSettings,
476+
jsonc.modify(rawSettings, ["remote.SSH.connectTimeout"], connTimeout, {}),
477+
),
478+
)
479+
} catch (error) {
480+
this.storage.writeToCoderOutputChannel(
481+
`Failed to reset remote.SSH.connectTimeout back to ${connTimeout}: ${error}`,
482+
)
483+
}
484+
})
485+
}
486+
448487
if (!pid) {
449488
// TODO: Show an error here!
450489
return

0 commit comments

Comments
 (0)