From 2763f4af2c97e9703dc31af46576b874efd5d6ca Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Thu, 2 Apr 2026 12:51:33 -0700 Subject: [PATCH] fix: make pid optional in RuntimeWorker interface pid may be undefined if worker hasn't started yet. Update implementations to return number | undefined. --- .../plugin/runtime/child-process-worker.ts | 18 ++++++++--------- server/src/plugin/runtime/python-worker.ts | 20 +++++++++---------- server/src/plugin/runtime/runtime-worker.ts | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/server/src/plugin/runtime/child-process-worker.ts b/server/src/plugin/runtime/child-process-worker.ts index caddcf877..fbd6f71b3 100644 --- a/server/src/plugin/runtime/child-process-worker.ts +++ b/server/src/plugin/runtime/child-process-worker.ts @@ -5,7 +5,7 @@ import { RuntimeWorker, RuntimeWorkerOptions } from "./runtime-worker"; export abstract class ChildProcessWorker extends EventEmitter implements RuntimeWorker { public pluginId: string; - protected worker: child_process.ChildProcess; + protected worker: child_process.ChildProcess | undefined; killPromise: Promise; get childProcess() { @@ -19,18 +19,18 @@ export abstract class ChildProcessWorker extends EventEmitter implements Runtime } setupWorker() { - this.worker.on('close', () => this.emit('error', new Error('close'))); - this.worker.on('disconnect', () => this.emit('error', new Error('disconnect'))); - this.worker.on('exit', (code, signal) => this.emit('exit', code, signal)); - this.worker.on('error', e => this.emit('error', e)); + this.worker!.on('close', () => this.emit('error', new Error('close'))); + this.worker!.on('disconnect', () => this.emit('error', new Error('disconnect'))); + this.worker!.on('exit', (code, signal) => this.emit('exit', code, signal)); + this.worker!.on('error', e => this.emit('error', e)); // aggressively catch errors // ECONNRESET can be raised when the child process is killed - for (const stdio of this.worker.stdio || []) { + for (const stdio of this.worker!.stdio || []) { if (stdio) stdio.on('error', e => this.emit('error', e)); } - this.killPromise = once(this.worker, 'exit').then(() => { }).catch(() => { }); + this.killPromise = once(this.worker!, 'exit').then(() => { }).catch(() => { }); } get pid() { @@ -38,11 +38,11 @@ export abstract class ChildProcessWorker extends EventEmitter implements Runtime } get stdout() { - return this.worker.stdout; + return this.worker!.stdout!; } get stderr() { - return this.worker.stderr; + return this.worker!.stderr!; } kill(): void { diff --git a/server/src/plugin/runtime/python-worker.ts b/server/src/plugin/runtime/python-worker.ts index 3c0480901..f0df7212a 100644 --- a/server/src/plugin/runtime/python-worker.ts +++ b/server/src/plugin/runtime/python-worker.ts @@ -13,7 +13,7 @@ import { RuntimeWorkerOptions } from "./runtime-worker"; export class PythonRuntimeWorker extends ChildProcessWorker { static { - if (!fs.existsSync(process.env.SCRYPTED_PYTHON_PATH)) { + if (!process.env.SCRYPTED_PYTHON_PATH || !fs.existsSync(process.env.SCRYPTED_PYTHON_PATH)) { try { const py = new PortablePython(packagedPythonVersion); const portablePython = py.executablePath; @@ -99,7 +99,7 @@ export class PythonRuntimeWorker extends ChildProcessWorker { const setup = () => { const types = require.resolve('@scrypted/types'); const PYTHONPATH = types.substring(0, types.indexOf('types') + 'types'.length); - this.worker = child_process.spawn(pythonPath, args, { + this.worker = child_process.spawn(pythonPath as string, args, { cwd: options.unzippedPath, // stdin, stdout, stderr, peer in, peer out stdio: ['pipe', 'pipe', 'pipe', 'pipe', 'pipe'], @@ -112,8 +112,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker { }); this.setupWorker(); - this.worker.stdout.pipe(this.stdout); - this.worker.stderr.pipe(this.stderr); + this.worker.stdout!.pipe(this.stdout); + this.worker.stderr!.pipe(this.stderr); }; let pluginPythonVersion: string = options.packageJson.scrypted.pythonVersion?.[os.platform()]?.[os.arch()] || options.packageJson.scrypted.pythonVersion?.default; @@ -125,8 +125,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker { // if the plugin requests a specific python, then install it via portable python if (!pluginPythonVersion) { setup(); - this.peerin = this.worker.stdio[3] as Writable; - this.peerout = this.worker.stdio[4] as Readable; + this.peerin = this.worker!.stdio[3]! as Writable; + this.peerout = this.worker!.stdio[4]! as Readable; return; } @@ -135,8 +135,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker { if (envPython && fs.existsSync(envPython)) { pythonPath = envPython; setup(); - this.peerin = this.worker.stdio[3] as Writable; - this.peerout = this.worker.stdio[4] as Readable; + this.peerin = this.worker!.stdio[3]! as Writable; + this.peerout = this.worker!.stdio[4]! as Readable; return; } @@ -146,8 +146,8 @@ export class PythonRuntimeWorker extends ChildProcessWorker { const finishSetup = () => { setup(); - peerin.pipe(this.worker.stdio[3] as Writable); - (this.worker.stdio[4] as Readable).pipe(peerout); + peerin.pipe(this.worker!.stdio[3]! as Writable); + (this.worker!.stdio[4]! as Readable).pipe(peerout); }; const pyVersion = require('py/package.json').version; diff --git a/server/src/plugin/runtime/runtime-worker.ts b/server/src/plugin/runtime/runtime-worker.ts index 9e2158b68..31ce5e5fa 100644 --- a/server/src/plugin/runtime/runtime-worker.ts +++ b/server/src/plugin/runtime/runtime-worker.ts @@ -13,7 +13,7 @@ export interface RuntimeWorkerOptions { } export interface RuntimeWorker { - pid: number; + pid: number | undefined; stdout: Readable; stderr: Readable; killPromise: Promise;