Skip to content

Fix #418: Debugger should retry if extension isn't loaded yet #429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2017
Merged
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
146 changes: 102 additions & 44 deletions src/debugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,49 +26,107 @@ var debugAdapterLogWriter =
// debug server
process.stdin.pause();

// Read the details of the current session to learn
// the connection details for the debug service
let sessionDetails = utils.readSessionFile();

// Establish connection before setting up the session
debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n");
let debugServiceSocket = net.connect(sessionDetails.debugServicePort, '127.0.0.1');

// Write any errors to the log file
debugServiceSocket.on(
'error',
(e) => debugAdapterLogWriter.write("Socket connect ERROR: " + e + "\r\n"));

// Route any output from the socket through stdout
debugServiceSocket.on(
'data',
(data: Buffer) => process.stdout.write(data));

// Wait for the connection to complete
debugServiceSocket.on(
'connect',
() => {
debugAdapterLogWriter.write("Connected to socket!\r\n\r\n");

// When data comes on stdin, route it through the socket
process.stdin.on(
'data',
(data: Buffer) => debugServiceSocket.write(data));

// Resume the stdin stream
process.stdin.resume();
});

// When the socket closes, end the session
debugServiceSocket.on(
'close',
() => {
debugAdapterLogWriter.write("Socket closed, shutting down.");

// Close after a short delay to give the client time
// to finish up
setTimeout(() => {
function startDebugging() {
// Read the details of the current session to learn
// the connection details for the debug service
let sessionDetails = utils.readSessionFile();

// Establish connection before setting up the session
debugAdapterLogWriter.write("Connecting to port: " + sessionDetails.debugServicePort + "\r\n");

let isConnected = false;
let debugServiceSocket = net.connect(sessionDetails.debugServicePort, '127.0.0.1');

// Write any errors to the log file
debugServiceSocket.on(
'error',
(e) => {
debugAdapterLogWriter.write("Socket ERROR: " + e + "\r\n")
debugAdapterLogWriter.close();
debugServiceSocket.destroy();
process.exit(0);
}, 1000);
});

// Route any output from the socket through stdout
debugServiceSocket.on(
'data',
(data: Buffer) => process.stdout.write(data));

// Wait for the connection to complete
debugServiceSocket.on(
'connect',
() => {
isConnected = true;
debugAdapterLogWriter.write("Connected to socket!\r\n\r\n");

// When data comes on stdin, route it through the socket
process.stdin.on(
'data',
(data: Buffer) => debugServiceSocket.write(data));

// Resume the stdin stream
process.stdin.resume();
});

// When the socket closes, end the session
debugServiceSocket.on(
'close',
() => {
debugAdapterLogWriter.write("Socket closed, shutting down.");
debugAdapterLogWriter.close();
isConnected = false;

// Close after a short delay to give the client time
// to finish up
setTimeout(() => {
process.exit(0);
}, 2000);
}
)

process.on(
'exit',
(e) => {
if (debugAdapterLogWriter) {
debugAdapterLogWriter.write("Debug adapter process is exiting...");
}
}
)
}

var sessionFilePath = utils.getSessionFilePath();
function waitForSessionFile(triesRemaining: number) {

debugAdapterLogWriter.write(`Waiting for session file, tries remaining: ${triesRemaining}...\r\n`);

if (triesRemaining > 0) {
if (utils.checkIfFileExists(sessionFilePath)) {
debugAdapterLogWriter.write(`Session file present, connecting to debug adapter...\r\n\r\n`);
startDebugging();
}
else {
// Wait for a second and try again
setTimeout(
() => waitForSessionFile(triesRemaining - 1),
1000);
}
}
else {
debugAdapterLogWriter.write(`Timed out waiting for session file!\r\n`);
var errorJson =
JSON.stringify({
type: "response",
request_seq: 1,
command: "initialize",
success: false,
message: "Timed out waiting for the PowerShell extension to start."
});

process.stdout.write(
`Content-Length: ${Buffer.byteLength(errorJson, 'utf8')}\r\n\r\n${errorJson}`,
'utf8');
}
)
}

// Wait for the session file to appear
waitForSessionFile(30);
4 changes: 4 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'use strict';

import vscode = require('vscode');
import utils = require('./utils');
import { Logger, LogLevel } from './logging';
import { IFeature } from './feature';
import { SessionManager } from './session';
Expand All @@ -28,6 +29,9 @@ var logger: Logger = undefined;
var sessionManager: SessionManager = undefined;
var extensionFeatures: IFeature[] = [];

// Clean up the session file just in case one lingers from a previous session
utils.deleteSessionFile();

export function activate(context: vscode.ExtensionContext): void {

vscode.languages.setLanguageConfiguration(
Expand Down
14 changes: 8 additions & 6 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,8 @@ export class SessionManager {
if (response["status"] === "started") {
let sessionDetails: utils.EditorServicesSessionDetails = response;

// Write out the session configuration file
utils.writeSessionFile(sessionDetails);

// Start the language service client
this.startLanguageClient(sessionDetails.languageServicePort);
this.startLanguageClient(sessionDetails);
}
else if (response["status"] === "failed") {
if (response["reason"] === "unsupported") {
Expand Down Expand Up @@ -326,19 +323,24 @@ export class SessionManager {
.then((answer) => { if (answer === "Yes") { this.restartSession(); }});
}

private startLanguageClient(port: number) {
private startLanguageClient(sessionDetails: utils.EditorServicesSessionDetails) {

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

try
{
this.log.write("Connecting to language service on port " + port + "..." + os.EOL);

let connectFunc = () => {
return new Promise<StreamInfo>(
(resolve, reject) => {
var socket = net.connect(port);
socket.on(
'connect',
() => {
// Write out the session configuration file
utils.writeSessionFile(sessionDetails);

this.log.write("Language service connected.");
resolve({writer: socket, reader: socket})
});
Expand Down