Skip to content

Commit 5b32676

Browse files
authored
Merge pull request PowerShell#429 from PowerShell/daviwil/debug-retry
Fix PowerShell#418: Debugger should retry if extension isn't loaded yet
2 parents 1626c3f + 1f1c6e4 commit 5b32676

File tree

3 files changed

+114
-50
lines changed

3 files changed

+114
-50
lines changed

src/debugAdapter.ts

+102-44
Original file line numberDiff line numberDiff line change
@@ -26,49 +26,107 @@ var debugAdapterLogWriter =
2626
// debug server
2727
process.stdin.pause();
2828

29-
// Read the details of the current session to learn
30-
// the connection details for the debug service
31-
let sessionDetails = utils.readSessionFile();
32-
33-
// Establish connection before setting up the session
34-
debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n");
35-
let debugServiceSocket = net.connect(sessionDetails.debugServicePort, '127.0.0.1');
36-
37-
// Write any errors to the log file
38-
debugServiceSocket.on(
39-
'error',
40-
(e) => debugAdapterLogWriter.write("Socket connect ERROR: " + e + "\r\n"));
41-
42-
// Route any output from the socket through stdout
43-
debugServiceSocket.on(
44-
'data',
45-
(data: Buffer) => process.stdout.write(data));
46-
47-
// Wait for the connection to complete
48-
debugServiceSocket.on(
49-
'connect',
50-
() => {
51-
debugAdapterLogWriter.write("Connected to socket!\r\n\r\n");
52-
53-
// When data comes on stdin, route it through the socket
54-
process.stdin.on(
55-
'data',
56-
(data: Buffer) => debugServiceSocket.write(data));
57-
58-
// Resume the stdin stream
59-
process.stdin.resume();
60-
});
61-
62-
// When the socket closes, end the session
63-
debugServiceSocket.on(
64-
'close',
65-
() => {
66-
debugAdapterLogWriter.write("Socket closed, shutting down.");
67-
68-
// Close after a short delay to give the client time
69-
// to finish up
70-
setTimeout(() => {
29+
function startDebugging() {
30+
// Read the details of the current session to learn
31+
// the connection details for the debug service
32+
let sessionDetails = utils.readSessionFile();
33+
34+
// Establish connection before setting up the session
35+
debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n");
36+
37+
let isConnected = false;
38+
let debugServiceSocket = net.connect(sessionDetails.debugServicePort, '127.0.0.1');
39+
40+
// Write any errors to the log file
41+
debugServiceSocket.on(
42+
'error',
43+
(e) => {
44+
debugAdapterLogWriter.write("Socket ERROR: " + e + "\r\n")
45+
debugAdapterLogWriter.close();
46+
debugServiceSocket.destroy();
7147
process.exit(0);
72-
}, 1000);
48+
});
49+
50+
// Route any output from the socket through stdout
51+
debugServiceSocket.on(
52+
'data',
53+
(data: Buffer) => process.stdout.write(data));
54+
55+
// Wait for the connection to complete
56+
debugServiceSocket.on(
57+
'connect',
58+
() => {
59+
isConnected = true;
60+
debugAdapterLogWriter.write("Connected to socket!\r\n\r\n");
61+
62+
// When data comes on stdin, route it through the socket
63+
process.stdin.on(
64+
'data',
65+
(data: Buffer) => debugServiceSocket.write(data));
66+
67+
// Resume the stdin stream
68+
process.stdin.resume();
69+
});
70+
71+
// When the socket closes, end the session
72+
debugServiceSocket.on(
73+
'close',
74+
() => {
75+
debugAdapterLogWriter.write("Socket closed, shutting down.");
76+
debugAdapterLogWriter.close();
77+
isConnected = false;
78+
79+
// Close after a short delay to give the client time
80+
// to finish up
81+
setTimeout(() => {
82+
process.exit(0);
83+
}, 2000);
84+
}
85+
)
86+
87+
process.on(
88+
'exit',
89+
(e) => {
90+
if (debugAdapterLogWriter) {
91+
debugAdapterLogWriter.write("Debug adapter process is exiting...");
92+
}
93+
}
94+
)
95+
}
96+
97+
var sessionFilePath = utils.getSessionFilePath();
98+
function waitForSessionFile(triesRemaining: number) {
99+
100+
debugAdapterLogWriter.write(`Waiting for session file, tries remaining: ${triesRemaining}...\r\n`);
101+
102+
if (triesRemaining > 0) {
103+
if (utils.checkIfFileExists(sessionFilePath)) {
104+
debugAdapterLogWriter.write(`Session file present, connecting to debug adapter...\r\n\r\n`);
105+
startDebugging();
106+
}
107+
else {
108+
// Wait for a second and try again
109+
setTimeout(
110+
() => waitForSessionFile(triesRemaining - 1),
111+
1000);
112+
}
113+
}
114+
else {
115+
debugAdapterLogWriter.write(`Timed out waiting for session file!\r\n`);
116+
var errorJson =
117+
JSON.stringify({
118+
type: "response",
119+
request_seq: 1,
120+
command: "initialize",
121+
success: false,
122+
message: "Timed out waiting for the PowerShell extension to start."
123+
});
124+
125+
process.stdout.write(
126+
`Content-Length: ${Buffer.byteLength(errorJson, 'utf8')}\r\n\r\n${errorJson}`,
127+
'utf8');
73128
}
74-
)
129+
}
130+
131+
// Wait for the session file to appear
132+
waitForSessionFile(30);

src/main.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'use strict';
66

77
import vscode = require('vscode');
8+
import utils = require('./utils');
89
import { Logger, LogLevel } from './logging';
910
import { IFeature } from './feature';
1011
import { SessionManager } from './session';
@@ -28,6 +29,9 @@ var logger: Logger = undefined;
2829
var sessionManager: SessionManager = undefined;
2930
var extensionFeatures: IFeature[] = [];
3031

32+
// Clean up the session file just in case one lingers from a previous session
33+
utils.deleteSessionFile();
34+
3135
export function activate(context: vscode.ExtensionContext): void {
3236

3337
vscode.languages.setLanguageConfiguration(

src/session.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,8 @@ export class SessionManager {
257257
if (response["status"] === "started") {
258258
let sessionDetails: utils.EditorServicesSessionDetails = response;
259259

260-
// Write out the session configuration file
261-
utils.writeSessionFile(sessionDetails);
262-
263260
// Start the language service client
264-
this.startLanguageClient(sessionDetails.languageServicePort);
261+
this.startLanguageClient(sessionDetails);
265262
}
266263
else if (response["status"] === "failed") {
267264
if (response["reason"] === "unsupported") {
@@ -326,19 +323,24 @@ export class SessionManager {
326323
.then((answer) => { if (answer === "Yes") { this.restartSession(); }});
327324
}
328325

329-
private startLanguageClient(port: number) {
326+
private startLanguageClient(sessionDetails: utils.EditorServicesSessionDetails) {
330327

331-
this.log.write("Connecting to language service on port " + port + "..." + os.EOL);
328+
var port = sessionDetails.languageServicePort;
332329

333330
try
334331
{
332+
this.log.write("Connecting to language service on port " + port + "..." + os.EOL);
333+
335334
let connectFunc = () => {
336335
return new Promise<StreamInfo>(
337336
(resolve, reject) => {
338337
var socket = net.connect(port);
339338
socket.on(
340339
'connect',
341340
() => {
341+
// Write out the session configuration file
342+
utils.writeSessionFile(sessionDetails);
343+
342344
this.log.write("Language service connected.");
343345
resolve({writer: socket, reader: socket})
344346
});

0 commit comments

Comments
 (0)