Skip to content

Commit 7836b16

Browse files
unity-cli@v1.0.13 (#14)
- add a timeout to unity-hub process that force kills it if its still alive after 5s when tasks are completed
1 parent 54b0cf4 commit 7836b16

5 files changed

Lines changed: 38 additions & 13 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rage-against-the-pixel/unity-cli",
3-
"version": "1.0.12",
3+
"version": "1.0.13",
44
"description": "A command line utility for the Unity Game Engine.",
55
"author": "RageAgainstThePixel",
66
"license": "MIT",

src/unity-editor.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
GetArgumentValueAsString,
66
KillChildProcesses,
77
ProcInfo,
8-
ReadPidFile,
98
TryKillProcess
109
} from './utilities';
1110
import {

src/unity-hub.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,17 @@ export class UnityHub {
105105
const tasksCompleteMessage = 'All Tasks Completed Successfully.';
106106
const child = spawn(executable, execArgs, {
107107
stdio: ['ignore', 'pipe', 'pipe'],
108+
detached: process.platform !== 'win32'
108109
});
109110
const sigintHandler = () => child.kill('SIGINT');
110111
const sigtermHandler = () => child.kill('SIGTERM');
111112
process.once('SIGINT', sigintHandler);
112113
process.once('SIGTERM', sigtermHandler);
114+
function removeListeners() {
115+
process.removeListener('SIGINT', sigintHandler);
116+
process.removeListener('SIGTERM', sigtermHandler);
117+
}
118+
let forceCloseTimeout: NodeJS.Timeout | undefined;
113119
function processOutput(data: Buffer) {
114120
try {
115121
const chunk = data.toString();
@@ -138,8 +144,21 @@ export class UnityHub {
138144
if (child?.pid) {
139145
Logger.instance.debug(`Unity Hub reported all tasks completed, terminating process...`);
140146
const childProcInfo = { pid: child.pid, name: child.spawnfile, ppid: process.pid };
141-
KillChildProcesses(childProcInfo);
142-
TryKillProcess(childProcInfo);
147+
KillChildProcesses(childProcInfo).then(async () => {
148+
const killedPid = await TryKillProcess(childProcInfo, 'SIGTERM');
149+
150+
if (!killedPid) {
151+
Logger.instance.error(`Failed to terminate Unity Hub process!`);
152+
}
153+
154+
// In case the process doesn't close itself, force kill after 5 seconds
155+
forceCloseTimeout = setTimeout(() => {
156+
Logger.instance.info(`Force closing Unity Hub process after timeout...`);
157+
TryKillProcess(childProcInfo, 'SIGKILL');
158+
removeListeners();
159+
resolve(0);
160+
}, 5000);
161+
});
143162
}
144163
}
145164
} catch (error: any) {
@@ -151,13 +170,19 @@ export class UnityHub {
151170
child.stdout.on('data', processOutput);
152171
child.stderr.on('data', processOutput);
153172
child.on('error', (error) => {
154-
process.removeListener('SIGINT', sigintHandler);
155-
process.removeListener('SIGTERM', sigtermHandler);
173+
if (forceCloseTimeout) {
174+
clearTimeout(forceCloseTimeout);
175+
}
176+
177+
removeListeners();
156178
reject(error);
157179
});
158180
child.on('close', (code) => {
159-
process.removeListener('SIGINT', sigintHandler);
160-
process.removeListener('SIGTERM', sigtermHandler);
181+
if (forceCloseTimeout) {
182+
clearTimeout(forceCloseTimeout);
183+
}
184+
185+
removeListeners();
161186

162187
if (tasksComplete) {
163188
resolve(0);

src/utilities.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,16 @@ export interface ProcInfo {
233233
/**
234234
* Attempts to kill a process with the given ProcInfo.
235235
* @param procInfo The process information containing the PID.
236+
* @param signal The signal to use for killing the process. Defaults to 'SIGTERM'.
236237
* @returns The PID of the killed process, or undefined if no process was killed.
237238
*/
238-
export async function TryKillProcess(procInfo: ProcInfo): Promise<number | undefined> {
239+
export async function TryKillProcess(procInfo: ProcInfo, signal: NodeJS.Signals = 'SIGTERM'): Promise<number | undefined> {
239240
let pid: number | undefined;
240241

241242
try {
243+
logger.ci(`Killing process "${procInfo.name}" with pid: ${procInfo.pid}`);
244+
process.kill(procInfo.pid, signal);
242245
pid = procInfo.pid;
243-
logger.ci(`Killing process "${procInfo.name}" with pid: ${pid}`);
244-
process.kill(pid, 'SIGTERM');
245246
} catch (error) {
246247
const nodeJsException = error as NodeJS.ErrnoException;
247248
const errorCode = nodeJsException?.code;

0 commit comments

Comments
 (0)