sub-process-handler
Version:
A utility for managing subprocesses in Node.js with enhanced control over detached processes.
108 lines (107 loc) • 3.91 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SubProcessHandler = void 0;
const child_process_1 = require("child_process");
class SubProcessHandler {
/**
* Creates a new subprocess handler
* @param command Command to execute (path to executable)
* @param args Arguments to pass to the command
* @param options Spawn options
*/
constructor(command, args = [], options = {}) {
this.process = null;
this.processId = null;
this.isRunning = false;
this.output = '';
this.error = null;
this.command = command;
this.args = args;
// Critical changes for process detachment to work properly
this.options = Object.assign({ detached: true, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true }, options);
this.startProcess();
}
startProcess() {
try {
this.process = (0, child_process_1.spawn)(this.command, this.args, this.options);
// Set process ID
this.processId = this.process.pid || null;
// Track if the process is running
this.isRunning = !!this.processId;
// Ensure stdout and stderr exist before attaching listeners
if (this.process.stdout) {
this.process.stdout.on('data', (data) => {
const dataStr = data.toString();
this.output += dataStr;
});
}
if (this.process.stderr) {
this.process.stderr.on('data', (data) => {
const dataStr = data.toString();
this.output += dataStr;
});
}
// Handle process exit
this.process.on('close', (code) => {
this.isRunning = false;
});
this.process.on('error', (err) => {
this.isRunning = false;
this.error = err;
});
// Properly detach the process
if (this.options.detached) {
this.process.unref();
}
}
catch (error) {
this.error = error;
this.isRunning = false;
}
}
getStatus() {
if (this.process && this.isRunning) {
try {
// Attempt to send a signal to the process to check if it's still alive
process.kill(this.process.pid, 0);
return 'Running';
}
catch (_a) {
this.isRunning = false;
return 'Not Running';
}
}
return 'Not Running';
}
getOutput() {
return this.output;
}
getError() {
return this.error;
}
killProcess() {
if (this.process && this.process.pid) {
try {
console.log(`Attempting to kill process with PID: ${this.process.pid}`);
// On Windows, we need a different approach to kill a detached process
if (process.platform === 'win32') {
// Kill process tree (may require additional logic for Windows)
(0, child_process_1.spawn)('taskkill', ['/pid', this.process.pid.toString(), '/f', '/t']);
}
else {
// On Unix-like systems, negative PID kills the process group
process.kill(-this.process.pid, 'SIGKILL');
}
this.isRunning = false;
console.log(`Process with PID ${this.process.pid} killed successfully`);
}
catch (error) {
console.error(`Failed to kill process: ${error}`);
}
}
else {
console.log('No process to kill or process ID is not available');
}
}
}
exports.SubProcessHandler = SubProcessHandler;