Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

fix(rome_cli): improve the logging of panics and connection errors #3957

Merged
merged 3 commits into from
Dec 5, 2022
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
8 changes: 7 additions & 1 deletion crates/rome_cli/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub fn setup_panic_handler() {
}

fn panic_handler(info: &PanicInfo) {
// Buffer the error message to a string before printing it to stderr at once
// Buffer the error message to a string before printing it at once
// to prevent it from getting mixed with other errors if multiple threads
// panic at the same time
let mut error = String::new();
Expand All @@ -37,5 +37,11 @@ fn panic_handler(info: &PanicInfo) {
writeln!(error, "Message: {msg}").unwrap();
}

// Write the panic to stderr
eprintln!("{error}");

// Write the panic to the log file, this is done last since the `tracing`
// infrastructure could panic a second time and abort the process, so we
// want to ensure the error has at least been logged to stderr beforehand
tracing::error!("{error}");
}
87 changes: 58 additions & 29 deletions editors/vscode/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { spawn } from "child_process";
import { connect } from "net";
import type { Readable } from "stream";
import { connect, type Socket } from "net";
import { promisify } from "util";
import {
ExtensionContext,
Expand Down Expand Up @@ -247,52 +248,80 @@ async function fileExists(path: Uri) {
}
}

function getSocket(
function collectStream(stream: Readable) {
return new Promise<string>((resolve, reject) => {
let buffer = "";
stream.on("data", (data) => {
buffer += data.toString("utf-8");
});

stream.on("error", reject);
stream.on("end", () => {
resolve(buffer);
});
});
}

async function getSocket(
outputChannel: OutputChannel,
command: string,
): Promise<string> {
return new Promise((resolve, reject) => {
const process = spawn(command, ["__print_socket"], {
stdio: "pipe",
});
const process = spawn(command, ["__print_socket"], {
stdio: "pipe",
});

const exitCode = new Promise<number>((resolve, reject) => {
process.on("error", reject);
process.on("exit", resolve);
});

let output = "";
process.stdout.on("data", (data) => {
output += data.toString("utf-8");
});
const [stdout, stderr, code] = await Promise.all([
collectStream(process.stdout),
collectStream(process.stderr),
exitCode,
]);

process.on("exit", (code) => {
if (code === 0) {
const pipeName = output.trimEnd();
outputChannel.appendLine(`Connecting to "${pipeName}" ...`);
resolve(pipeName);
} else {
reject(code);
}
});
});
const pipeName = stdout.trimEnd();

if (code !== 0 || pipeName.length === 0) {
let message = `Command "${command} __print_socket" exited with code ${code}`;
if (stderr.length > 0) {
message += `\nOutput:\n${stderr}`;
}

throw new Error(message);
} else {
outputChannel.appendLine(`Connecting to "${pipeName}" ...`);
return pipeName;
}
}

function wrapConnectionError(err: Error, path: string): Error {
return Object.assign(
new Error(
`Could not connect to the Rome server at "${path}": ${err.message}`,
),
{ name: err.name, stack: err.stack },
);
}

async function createMessageTransports(
outputChannel: OutputChannel,
command: string,
): Promise<StreamInfo> {
const path = await getSocket(outputChannel, command);
const socket = connect(path);

let socket: Socket;
try {
socket = connect(path);
} catch (err) {
throw wrapConnectionError(err, path);
}

await new Promise((resolve, reject) => {
socket.once("ready", resolve);
socket.once("error", (err) => {
reject(
Object.assign(
new Error(
`Could not connect to the Rome server at "${path}": ${err.message}`,
),
{ name: err.name, stack: err.stack },
),
);
reject(wrapConnectionError(err, path));
});
});

Expand Down