Skip to content

Commit daf36f3

Browse files
author
Eric Wheeler
committed
refactor: move interpretExitCode from TerminalManager to TerminalProcess
This commit moves the interpretExitCode method from TerminalManager to TerminalProcess class, as part of the terminal refactoring effort. The method is responsible for translating exit codes into detailed results, including signal information. Changes include: - Moved interpretExitCode method to TerminalProcess class - Updated imports in TerminalManager and Cline to reference ExitCodeDetails from TerminalProcess - Added findTerminalIdByVscodeTerminal helper method in TerminalManager - Added comprehensive unit tests for interpretExitCode in TerminalProcess - Tests cover undefined exit codes, normal exit codes (0-127), and signal exit codes (128+) This change improves code organization by placing the exit code interpretation logic closer to where it's primarily used, in the TerminalProcess class. Signed-off-by: Eric Wheeler <[email protected]>
1 parent 3a950bb commit daf36f3

File tree

4 files changed

+281
-105
lines changed

4 files changed

+281
-105
lines changed

src/core/Cline.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import {
2727
everyLineHasLineNumbers,
2828
truncateOutput,
2929
} from "../integrations/misc/extract-text"
30-
import { TerminalManager, ExitCodeDetails } from "../integrations/terminal/TerminalManager"
30+
import { TerminalManager } from "../integrations/terminal/TerminalManager"
31+
import { ExitCodeDetails } from "../integrations/terminal/TerminalProcess"
3132
import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
3233
import { listFiles } from "../services/glob/list-files"
3334
import { regexSearchFiles } from "../services/ripgrep"

src/integrations/terminal/TerminalManager.ts

Lines changed: 20 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pWaitFor from "p-wait-for"
22
import * as vscode from "vscode"
33
import { arePathsEqual } from "../../utils/path"
4-
import { mergePromise, TerminalProcess, TerminalProcessResultPromise } from "./TerminalProcess"
4+
import { ExitCodeDetails, mergePromise, TerminalProcess, TerminalProcessResultPromise } from "./TerminalProcess"
55
import { Terminal } from "./Terminal"
66
import { TerminalRegistry } from "./TerminalRegistry"
77

@@ -95,112 +95,11 @@ declare module "vscode" {
9595
}
9696
}
9797

98-
export interface ExitCodeDetails {
99-
exitCode: number | undefined
100-
signal?: number | undefined
101-
signalName?: string
102-
coreDumpPossible?: boolean
103-
}
104-
10598
export class TerminalManager {
10699
private terminalIds: Set<number> = new Set()
107100
private processes: Map<number, TerminalProcess> = new Map()
108101
private disposables: vscode.Disposable[] = []
109102

110-
private interpretExitCode(exitCode: number | undefined): ExitCodeDetails {
111-
if (exitCode === undefined) {
112-
return { exitCode }
113-
}
114-
115-
if (exitCode <= 128) {
116-
return { exitCode }
117-
}
118-
119-
const signal = exitCode - 128
120-
const signals: Record<number, string> = {
121-
// Standard signals
122-
1: "SIGHUP",
123-
2: "SIGINT",
124-
3: "SIGQUIT",
125-
4: "SIGILL",
126-
5: "SIGTRAP",
127-
6: "SIGABRT",
128-
7: "SIGBUS",
129-
8: "SIGFPE",
130-
9: "SIGKILL",
131-
10: "SIGUSR1",
132-
11: "SIGSEGV",
133-
12: "SIGUSR2",
134-
13: "SIGPIPE",
135-
14: "SIGALRM",
136-
15: "SIGTERM",
137-
16: "SIGSTKFLT",
138-
17: "SIGCHLD",
139-
18: "SIGCONT",
140-
19: "SIGSTOP",
141-
20: "SIGTSTP",
142-
21: "SIGTTIN",
143-
22: "SIGTTOU",
144-
23: "SIGURG",
145-
24: "SIGXCPU",
146-
25: "SIGXFSZ",
147-
26: "SIGVTALRM",
148-
27: "SIGPROF",
149-
28: "SIGWINCH",
150-
29: "SIGIO",
151-
30: "SIGPWR",
152-
31: "SIGSYS",
153-
154-
// Real-time signals base
155-
34: "SIGRTMIN",
156-
157-
// SIGRTMIN+n signals
158-
35: "SIGRTMIN+1",
159-
36: "SIGRTMIN+2",
160-
37: "SIGRTMIN+3",
161-
38: "SIGRTMIN+4",
162-
39: "SIGRTMIN+5",
163-
40: "SIGRTMIN+6",
164-
41: "SIGRTMIN+7",
165-
42: "SIGRTMIN+8",
166-
43: "SIGRTMIN+9",
167-
44: "SIGRTMIN+10",
168-
45: "SIGRTMIN+11",
169-
46: "SIGRTMIN+12",
170-
47: "SIGRTMIN+13",
171-
48: "SIGRTMIN+14",
172-
49: "SIGRTMIN+15",
173-
174-
// SIGRTMAX-n signals
175-
50: "SIGRTMAX-14",
176-
51: "SIGRTMAX-13",
177-
52: "SIGRTMAX-12",
178-
53: "SIGRTMAX-11",
179-
54: "SIGRTMAX-10",
180-
55: "SIGRTMAX-9",
181-
56: "SIGRTMAX-8",
182-
57: "SIGRTMAX-7",
183-
58: "SIGRTMAX-6",
184-
59: "SIGRTMAX-5",
185-
60: "SIGRTMAX-4",
186-
61: "SIGRTMAX-3",
187-
62: "SIGRTMAX-2",
188-
63: "SIGRTMAX-1",
189-
64: "SIGRTMAX",
190-
}
191-
192-
// These signals may produce core dumps:
193-
// SIGQUIT, SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV
194-
const coreDumpPossible = new Set([3, 4, 6, 7, 8, 11])
195-
196-
return {
197-
exitCode,
198-
signal,
199-
signalName: signals[signal] || `Unknown Signal (${signal})`,
200-
coreDumpPossible: coreDumpPossible.has(signal),
201-
}
202-
}
203-
204103
constructor() {
205104
let startDisposable: vscode.Disposable | undefined
206105
let endDisposable: vscode.Disposable | undefined
@@ -231,7 +130,10 @@ export class TerminalManager {
231130

232131
// onDidEndTerminalShellExecution
233132
endDisposable = (vscode.window as vscode.Window).onDidEndTerminalShellExecution?.(async (e) => {
234-
const exitDetails = this.interpretExitCode(e?.exitCode)
133+
// Find the terminal ID by the VSCode terminal instance
134+
const terminalId = this.findTerminalIdByVscodeTerminal(e.terminal)
135+
const process = terminalId !== undefined ? this.processes.get(terminalId) : undefined
136+
const exitDetails = process ? process.interpretExitCode(e?.exitCode) : { exitCode: e?.exitCode }
235137
console.info("[TerminalManager] Shell execution ended:", {
236138
...exitDetails,
237139
})
@@ -356,6 +258,21 @@ export class TerminalManager {
356258
return process ? process.getUnretrievedOutput() : ""
357259
}
358260

261+
/**
262+
* Finds the terminal ID by the VSCode terminal instance
263+
* @param terminal The VSCode terminal instance
264+
* @returns The terminal ID or undefined if not found
265+
*/
266+
private findTerminalIdByVscodeTerminal(terminal: vscode.Terminal): number | undefined {
267+
for (const id of this.terminalIds) {
268+
const info = TerminalRegistry.getTerminal(id)
269+
if (info && info.terminal === terminal) {
270+
return id
271+
}
272+
}
273+
return undefined
274+
}
275+
359276
isProcessHot(terminalId: number): boolean {
360277
const process = this.processes.get(terminalId)
361278
return process ? process.isHot : false

src/integrations/terminal/TerminalProcess.ts

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import stripAnsi from "strip-ansi"
33
import * as vscode from "vscode"
44
import { inspect } from "util"
55

6-
import { ExitCodeDetails } from "./TerminalManager"
6+
export interface ExitCodeDetails {
7+
exitCode: number | undefined
8+
signal?: number | undefined
9+
signalName?: string
10+
coreDumpPossible?: boolean
11+
}
712
import { Terminal } from "./Terminal"
813
import { TerminalRegistry } from "./TerminalRegistry"
914

@@ -34,6 +39,100 @@ export class TerminalProcess extends EventEmitter<TerminalProcessEvents> {
3439
private fullOutput: string = ""
3540
private lastRetrievedIndex: number = 0
3641
isHot: boolean = false
42+
43+
interpretExitCode(exitCode: number | undefined): ExitCodeDetails {
44+
if (exitCode === undefined) {
45+
return { exitCode }
46+
}
47+
48+
if (exitCode <= 128) {
49+
return { exitCode }
50+
}
51+
52+
const signal = exitCode - 128
53+
const signals: Record<number, string> = {
54+
// Standard signals
55+
1: "SIGHUP",
56+
2: "SIGINT",
57+
3: "SIGQUIT",
58+
4: "SIGILL",
59+
5: "SIGTRAP",
60+
6: "SIGABRT",
61+
7: "SIGBUS",
62+
8: "SIGFPE",
63+
9: "SIGKILL",
64+
10: "SIGUSR1",
65+
11: "SIGSEGV",
66+
12: "SIGUSR2",
67+
13: "SIGPIPE",
68+
14: "SIGALRM",
69+
15: "SIGTERM",
70+
16: "SIGSTKFLT",
71+
17: "SIGCHLD",
72+
18: "SIGCONT",
73+
19: "SIGSTOP",
74+
20: "SIGTSTP",
75+
21: "SIGTTIN",
76+
22: "SIGTTOU",
77+
23: "SIGURG",
78+
24: "SIGXCPU",
79+
25: "SIGXFSZ",
80+
26: "SIGVTALRM",
81+
27: "SIGPROF",
82+
28: "SIGWINCH",
83+
29: "SIGIO",
84+
30: "SIGPWR",
85+
31: "SIGSYS",
86+
87+
// Real-time signals base
88+
34: "SIGRTMIN",
89+
90+
// SIGRTMIN+n signals
91+
35: "SIGRTMIN+1",
92+
36: "SIGRTMIN+2",
93+
37: "SIGRTMIN+3",
94+
38: "SIGRTMIN+4",
95+
39: "SIGRTMIN+5",
96+
40: "SIGRTMIN+6",
97+
41: "SIGRTMIN+7",
98+
42: "SIGRTMIN+8",
99+
43: "SIGRTMIN+9",
100+
44: "SIGRTMIN+10",
101+
45: "SIGRTMIN+11",
102+
46: "SIGRTMIN+12",
103+
47: "SIGRTMIN+13",
104+
48: "SIGRTMIN+14",
105+
49: "SIGRTMIN+15",
106+
107+
// SIGRTMAX-n signals
108+
50: "SIGRTMAX-14",
109+
51: "SIGRTMAX-13",
110+
52: "SIGRTMAX-12",
111+
53: "SIGRTMAX-11",
112+
54: "SIGRTMAX-10",
113+
55: "SIGRTMAX-9",
114+
56: "SIGRTMAX-8",
115+
57: "SIGRTMAX-7",
116+
58: "SIGRTMAX-6",
117+
59: "SIGRTMAX-5",
118+
60: "SIGRTMAX-4",
119+
61: "SIGRTMAX-3",
120+
62: "SIGRTMAX-2",
121+
63: "SIGRTMAX-1",
122+
64: "SIGRTMAX",
123+
}
124+
125+
// These signals may produce core dumps:
126+
// SIGQUIT, SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV
127+
const coreDumpPossible = new Set([3, 4, 6, 7, 8, 11])
128+
129+
return {
130+
exitCode,
131+
signal,
132+
signalName: signals[signal] || `Unknown Signal (${signal})`,
133+
coreDumpPossible: coreDumpPossible.has(signal),
134+
}
135+
}
37136
private hotTimer: NodeJS.Timeout | null = null
38137

39138
async run(terminal: vscode.Terminal, command: string) {

0 commit comments

Comments
 (0)