diff options
| author | David Czihak <git@dcz.at> | 2026-05-09 01:30:32 +0200 |
|---|---|---|
| committer | David Czihak <git@dcz.at> | 2026-05-09 01:30:32 +0200 |
| commit | 4c3e7ea293b2e5a4929781e1b97a2f6affff6576 (patch) | |
| tree | 7799581d02da28b0aac88261f402ab4efa160edb /Scripts | |
| parent | d6dc191a9237b1be62d4fe729750a5af1ddd470e (diff) | |
Fix: Prevent hangs and failures in task system
A few async functions were swallowing errors or could leave commands stuck waiting forever:
- The »Open in Terminal« command could hang if osascript failed to start. It now reports the failure instead.
- ZLS config sync ran without error handling. Errors now show up in the log.
- Task discovery would block indefinitely if `zig build --list-steps` got stuck. It now gives up after a minute and moves on.
Diffstat (limited to 'Scripts')
| -rw-r--r-- | Scripts/main.js | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/Scripts/main.js b/Scripts/main.js index 652e4cc..24f8cde 100644 --- a/Scripts/main.js +++ b/Scripts/main.js @@ -446,6 +446,7 @@ const stepCache = { const result = await runProcess(zigPath, { args: ["build", "--list-steps"], cwd, + timeoutMs: 60000, }); if (result.status !== 0) return null; @@ -503,19 +504,30 @@ function localizeText(key, fallback, variables) { * Wraps Nova's Process API in a Promise, resolving with stdout, stderr, and exit status. * * @param {string} command - Absolute path to the executable - * @param {Object} options - Options passed to Nova's Process constructor (args, cwd, env, …) + * @param {Object} options - Options passed to Nova's Process constructor (args, cwd, env, …); + * the optional `timeoutMs` is consumed here and removed before construction * @returns {Promise<{status: number, stdout: string, stderr: string}>} */ function runProcess(command, options) { return new Promise((resolve, reject) => { const stdout = []; const stderr = []; - const process = new Process(command, options || {}); + const { timeoutMs, ...processOptions } = options || {}; + const process = new Process(command, processOptions); + + let settled = false; + let timer = null; + const settle = (result) => { + if (settled) return; + settled = true; + if (timer) clearTimeout(timer); + resolve(result); + }; process.onStdout((line) => stdout.push(line)); process.onStderr((line) => stderr.push(line)); process.onDidExit((status) => { - resolve({ + settle({ status, stdout: stdout.join(""), stderr: stderr.join(""), @@ -525,7 +537,24 @@ function runProcess(command, options) { try { process.start(); } catch (error) { + if (timer) clearTimeout(timer); reject(error); + return; + } + + if (typeof timeoutMs === "number" && timeoutMs > 0) { + timer = setTimeout(() => { + try { + if (typeof process.signal === "function") { + process.signal("SIGTERM"); + } + } catch (_) {} + settle({ + status: -1, + stdout: stdout.join(""), + stderr: `${stderr.join("")}\n[timeout after ${timeoutMs}ms]`, + }); + }, timeoutMs); } }); } @@ -756,7 +785,12 @@ end tell`; process.onDidExit((status) => { resolve({ status, stderr: stderr.trim() }); }); - process.start(); + + try { + process.start(); + } catch (error) { + resolve({ status: -1, stderr: String(error) }); + } }); } @@ -843,7 +877,12 @@ class ZigLanguageServer { if (restart) { this.start(); } else { - void this.pushConfiguration(); + this.pushConfiguration().catch((error) => { + console.error( + `[${LANGUAGE_CLIENT_ID}] pushConfiguration failed`, + error, + ); + }); } }), ); @@ -852,7 +891,12 @@ class ZigLanguageServer { if (restart) { this.start(); } else { - void this.pushConfiguration(); + this.pushConfiguration().catch((error) => { + console.error( + `[${LANGUAGE_CLIENT_ID}] pushConfiguration failed`, + error, + ); + }); } }), ); @@ -955,7 +999,12 @@ class ZigLanguageServer { client.start(); this.client = client; nova.subscriptions.add(client); - void this.pushConfiguration(); + this.pushConfiguration().catch((error) => { + console.error( + `[${LANGUAGE_CLIENT_ID}] pushConfiguration failed`, + error, + ); + }); this.warnedMissing.delete("zls"); if (zigPath) { this.warnedMissing.delete("zig"); |
