From 3c8f94ab2febf428488125ae0feb3e130307eb35 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Tue, 20 Aug 2024 23:20:04 -0700 Subject: [PATCH] server: Fix electron display var --- server/package-lock.json | 4 +-- server/src/plugin/runtime/electron-worker.ts | 31 ++++++++++++++++++-- server/src/plugin/runtime/runtime-host.ts | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 4a3e8def4..9e30905ec 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/server", - "version": "0.115.27", + "version": "0.115.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/server", - "version": "0.115.27", + "version": "0.115.28", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/server/src/plugin/runtime/electron-worker.ts b/server/src/plugin/runtime/electron-worker.ts index 867bc620d..2ffdc5f8a 100644 --- a/server/src/plugin/runtime/electron-worker.ts +++ b/server/src/plugin/runtime/electron-worker.ts @@ -5,15 +5,17 @@ import { RpcMessage, RpcPeer } from "../../rpc"; import { SidebandSocketSerializer } from "../socket-serializer"; import { ChildProcessWorker } from "./child-process-worker"; import { RuntimeWorkerOptions } from "./runtime-worker"; +import type { ScryptedRuntime } from '../../runtime'; export class ElectronForkWorker extends ChildProcessWorker { + static allocatedDisplays = new Set(); + allocatedDisplay: number; - constructor(mainFilename: string, pluginId: string, options: RuntimeWorkerOptions) { + constructor(mainFilename: string, pluginId: string, options: RuntimeWorkerOptions, runtime: ScryptedRuntime) { super(pluginId, options); const { env, pluginDebug } = options; - const execArgv: string[] = process.execArgv.slice(); if (pluginDebug) { // execArgv.push(`--inspect=0.0.0.0:${pluginDebug.inspectPort}`); @@ -23,8 +25,22 @@ export class ElectronForkWorker extends ChildProcessWorker { const electronBin: string = require('electron'); const args = [electronBin]; if (process.platform === 'linux') { + // crappy but should work. + for (let i = 50; i < 100; i++) { + if (!ElectronForkWorker.allocatedDisplays.has(i)) { + this.allocatedDisplay = i; + break; + } + } + + if (!this.allocatedDisplay) + throw new Error('unable to allocate DISPLAY for xvfb-run'); + + ElectronForkWorker.allocatedDisplays.add(this.allocatedDisplay); + // requires xvfb-run as electron does not support the chrome --headless flag. - args.unshift('xvfb-run', '-n', '0'); + // dummy up a DISPLAY env variable. this value numerical because of the way it is. + args.unshift('xvfb-run', '-n', this.allocatedDisplay.toString()); // https://github.com/gpuweb/gpuweb/wiki/Implementation-Status#chromium-chrome-edge-etc args.push('--no-sandbox', '--enable-unsafe-webgpu', '--ignore-gpu-blocklist', '--enable-features=Vulkan', '--disable-vulkan-surface'); } @@ -47,6 +63,9 @@ export class ElectronForkWorker extends ChildProcessWorker { // execArgv, }); + this.worker.on('exit', () => { + }); + this.worker.send({ pluginId, options, @@ -55,6 +74,12 @@ export class ElectronForkWorker extends ChildProcessWorker { this.setupWorker(); } + kill(): void { + super.kill(); + if (this.worker) + ElectronForkWorker.allocatedDisplays.delete(this.allocatedDisplay); + } + setupRpcPeer(peer: RpcPeer): void { this.worker.on('message', (message, sendHandle) => { if ((message as any).type && sendHandle) { diff --git a/server/src/plugin/runtime/runtime-host.ts b/server/src/plugin/runtime/runtime-host.ts index 4a042c549..ce4428578 100644 --- a/server/src/plugin/runtime/runtime-host.ts +++ b/server/src/plugin/runtime/runtime-host.ts @@ -13,7 +13,7 @@ export function getBuiltinRuntimeHosts() { pluginHosts.set('custom', (_, pluginId, options, runtime) => new CustomRuntimeWorker(pluginId, options, runtime)); pluginHosts.set('python', (_, pluginId, options) => new PythonRuntimeWorker(pluginId, options)); pluginHosts.set('node', (mainFilename, pluginId, options) => new NodeForkWorker(mainFilename, pluginId, options)); - pluginHosts.set('electron', (mainFilename, pluginId, options) => new ElectronForkWorker(mainFilename, pluginId, options)); + pluginHosts.set('electron', (mainFilename, pluginId, options, runtime) => new ElectronForkWorker(mainFilename, pluginId, options, runtime)); return pluginHosts; }