diff --git a/server/src/plugin/plugin-remote-worker.ts b/server/src/plugin/plugin-remote-worker.ts index 90b5a950f..d69b975db 100644 --- a/server/src/plugin/plugin-remote-worker.ts +++ b/server/src/plugin/plugin-remote-worker.ts @@ -1,5 +1,5 @@ import { RpcMessage, RpcPeer } from '../rpc'; -import { SystemManager, DeviceManager, ScryptedNativeId } from '@scrypted/types' +import { SystemManager, DeviceManager, ScryptedNativeId, ScryptedStatic } from '@scrypted/types' import { attachPluginRemote, PluginReader } from './plugin-remote'; import { PluginAPI } from './plugin-api'; import { MediaManagerImpl } from './media'; @@ -169,6 +169,8 @@ export function startPluginRemote(pluginId: string, peerSend: (message: RpcMessa return _pluginConsole; } + let postInstallSourceMapSupport: (scrypted: ScryptedStatic) => void; + attachPluginRemote(peer, { createMediaManager: async (sm) => { systemManager = sm; @@ -180,6 +182,7 @@ export function startPluginRemote(pluginId: string, peerSend: (message: RpcMessa }, onPluginReady: async (scrypted, params, plugin) => { replPort = createREPLServer(scrypted, params, plugin); + postInstallSourceMapSupport(scrypted); }, getPluginConsole, getDeviceConsole, @@ -196,37 +199,42 @@ export function startPluginRemote(pluginId: string, peerSend: (message: RpcMessa const entry = pluginReader('main.nodejs.js.map') const map = entry?.toString(); - installSourceMapSupport({ - environment: 'node', - retrieveSourceMap(source) { - if (source === '/plugin/main.nodejs.js' || source === `/${pluginId}/main.nodejs.js`) { - if (!map) - return null; - return { - url: '/plugin/main.nodejs.js', - map, + // plugins may install their own sourcemap support during startup, so + // hook the sourcemap installation after everything is loaded. + postInstallSourceMapSupport = (scrypted) => { + process.removeAllListeners('uncaughtException'); + process.removeAllListeners('unhandledRejection'); + + process.on('uncaughtException', e => { + getPluginConsole().error('uncaughtException', e); + scrypted.log.e('uncaughtException ' + e?.toString()); + }); + process.on('unhandledRejection', e => { + getPluginConsole().error('unhandledRejection', e); + scrypted.log.e('unhandledRejection ' + e?.toString()); + }); + + installSourceMapSupport({ + environment: 'node', + retrieveSourceMap(source) { + if (source === '/plugin/main.nodejs.js' || source === `/${pluginId}/main.nodejs.js`) { + if (!map) + return null; + return { + url: '/plugin/main.nodejs.js', + map, + } } + return null; } - return null; - } - }); + }); + }; + await installOptionalDependencies(getPluginConsole(), packageJson); } }).then(scrypted => { systemManager = scrypted.systemManager; deviceManager = scrypted.deviceManager; - - process.removeAllListeners('uncaughtException'); - process.removeAllListeners('unhandledRejection'); - - process.on('uncaughtException', e => { - getPluginConsole().error('uncaughtException', e); - scrypted.log.e('uncaughtException ' + e?.toString()); - }); - process.on('unhandledRejection', e => { - getPluginConsole().error('unhandledRejection', e); - scrypted.log.e('unhandledRejection ' + e?.toString()); - }); }); return peer; diff --git a/server/src/scrypted-main.ts b/server/src/scrypted-main.ts index 4501b137a..2e1d074a7 100644 --- a/server/src/scrypted-main.ts +++ b/server/src/scrypted-main.ts @@ -10,6 +10,8 @@ if (!semver.gte(process.version, '16.0.0')) { startPeriodicGarbageCollection(); if (process.argv[2] === 'child' || process.argv[2] === 'child-thread') { + // plugins should never crash. this handler will be removed, and then readded + // after the plugin source map is retrieved. process.on('uncaughtException', e => { console.error('uncaughtException', e); }); @@ -20,6 +22,7 @@ if (process.argv[2] === 'child' || process.argv[2] === 'child-thread') { require('./scrypted-plugin-main'); } else { + // unhandled rejections are allowed if they are from a rpc/plugin call. process.on('unhandledRejection', error => { if (error?.constructor !== RPCResultError && error?.constructor !== PluginError) { console.error('wtf', error); diff --git a/server/src/scrypted-plugin-main.ts b/server/src/scrypted-plugin-main.ts index 556ceb9a0..7cb509b98 100644 --- a/server/src/scrypted-plugin-main.ts +++ b/server/src/scrypted-plugin-main.ts @@ -24,7 +24,7 @@ else { })); peer.transportSafeArgumentTypes.add(Buffer.name); - process.on('message', message=> peer.handleMessage(message as RpcMessage)); + process.on('message', message => peer.handleMessage(message as RpcMessage)); process.on('disconnect', () => { console.error('peer host disconnected, exiting.'); process.exit(1);