Skip to content

Commit d9e4a83

Browse files
committed
Correctly Manage Child Processes
1 parent 0cd4550 commit d9e4a83

2 files changed

Lines changed: 51 additions & 50 deletions

File tree

CodeEdit/Features/Tasks/Models/CEActiveTask.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,42 +96,38 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable {
9696
}
9797

9898
func suspend() {
99-
if let output, status == .running {
100-
for pid in output.runningChildProcesses() {
101-
kill(pid, SIGSTOP)
102-
}
99+
if let pid = output?.runningPID(), status == .running {
100+
kill(pid, SIGSTOP)
103101
updateTaskStatus(to: .stopped)
104102
}
105103
}
106104

107105
func resume() {
108-
if let output, status == .stopped {
109-
for pid in output.runningChildProcesses() {
110-
kill(pid, SIGCONT)
111-
}
106+
if let pid = output?.runningPID(), status == .stopped {
107+
kill(pid, SIGCONT)
112108
updateTaskStatus(to: .running)
113109
}
114110
}
115111

116112
func terminate() {
117113
if let output {
118-
for pid in output.runningChildProcesses() {
114+
for pid in output.getChildProcesses() {
119115
kill(pid, SIGTERM)
120116
}
121117
}
122118
}
123119

124120
func interrupt() {
125121
if let output {
126-
for pid in output.runningChildProcesses() {
122+
for pid in output.getChildProcesses() {
127123
kill(pid, SIGINT)
128124
}
129125
}
130126
}
131127

132128
func clearOutput() {
133-
// TODO: - Clear Output
134-
// output?.feed(text: "\033[2J") // same command as 'clear'
129+
output?.terminal.resetToInitialState()
130+
output?.feed(text: "")
135131
}
136132

137133
private func createStatusTaskNotification() {

CodeEdit/Features/TerminalEmulator/Views/CEActiveTaskTerminalView.swift

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import SwiftTerm
1111
class CEActiveTaskTerminalView: CELocalShellTerminalView {
1212
var activeTask: CEActiveTask
1313

14-
var cachedCaretColor: NSColor?
15-
var isUserCommandRunning: Bool = false
16-
var enableOutput: Bool = false
14+
private var cachedCaretColor: NSColor?
15+
private var isUserCommandRunning: Bool = false
16+
private var enableOutput: Bool = false
1717

1818
init(activeTask: CEActiveTask) {
1919
self.activeTask = activeTask
@@ -131,14 +131,52 @@ class CEActiveTaskTerminalView: CELocalShellTerminalView {
131131
feed(byteArray: [13, 13, 10])
132132
}
133133

134-
func runningChildProcesses() -> [Int32] {
135-
getChildProcessesLibproc(parentPID: process.shellPid)
134+
func runningPID() -> pid_t? {
135+
if process.shellPid != 0 {
136+
return process.shellPid
137+
}
138+
return nil
139+
}
140+
141+
func getChildProcesses() -> [pid_t] {
142+
var children: [pid_t] = []
143+
guard let parentPID = runningPID() else { return [] }
144+
145+
// Get number of processes
146+
let numProcs = proc_listallpids(nil, 0)
147+
guard numProcs > 0 else { return children }
148+
149+
// Allocate buffer for PIDs
150+
let pids = UnsafeMutablePointer<pid_t>.allocate(capacity: Int(numProcs))
151+
defer { pids.deallocate() }
152+
153+
// Get all PIDs
154+
let actualNumProcs = proc_listallpids(pids, numProcs * Int32(MemoryLayout<pid_t>.size))
155+
156+
// Check each process
157+
for idx in 0..<Int(actualNumProcs) {
158+
var taskInfo = proc_taskallinfo()
159+
let size = proc_pidinfo(
160+
pids[idx],
161+
PROC_PIDTASKALLINFO,
162+
0,
163+
&taskInfo,
164+
Int32(MemoryLayout<proc_taskallinfo>.size)
165+
)
166+
167+
if size > 0 && taskInfo.pbsd.pbi_ppid == parentPID {
168+
children.append(pids[idx])
169+
}
170+
}
171+
172+
return children
136173
}
137174

138175
override func dataReceived(slice: ArraySlice<UInt8>) {
139176
if enableOutput {
140177
super.dataReceived(slice: slice)
141178
} else if slice.count >= 5 {
179+
// ESC [ 1 3 3 in UTF8
142180
let sequence: [UInt8] = [0x1B, 0x5D, 0x31, 0x33, 0x33]
143181
// Ignore until we see an OSC 133 code
144182
for idx in 0..<(slice.count - 5) where slice[idx..<idx + 5] == sequence[0..<5] {
@@ -148,36 +186,3 @@ class CEActiveTaskTerminalView: CELocalShellTerminalView {
148186
}
149187
}
150188
}
151-
152-
func getChildProcessesLibproc(parentPID: Int32) -> [Int32] {
153-
var children: [Int32] = []
154-
155-
// Get number of processes
156-
let numProcs = proc_listallpids(nil, 0)
157-
guard numProcs > 0 else { return children }
158-
159-
// Allocate buffer for PIDs
160-
let pids = UnsafeMutablePointer<pid_t>.allocate(capacity: Int(numProcs))
161-
defer { pids.deallocate() }
162-
163-
// Get all PIDs
164-
let actualNumProcs = proc_listallpids(pids, numProcs * Int32(MemoryLayout<pid_t>.size))
165-
166-
// Check each process
167-
for idx in 0..<Int(actualNumProcs) {
168-
var taskInfo = proc_taskallinfo()
169-
let size = proc_pidinfo(
170-
pids[idx],
171-
PROC_PIDTASKALLINFO,
172-
0,
173-
&taskInfo,
174-
Int32(MemoryLayout<proc_taskallinfo>.size)
175-
)
176-
177-
if size > 0 && taskInfo.pbsd.pbi_ppid == parentPID {
178-
children.append(pids[idx])
179-
}
180-
}
181-
182-
return children
183-
}

0 commit comments

Comments
 (0)