Skip to content

Commit

Permalink
server: fix potential race conditions around plugin restart
Browse files Browse the repository at this point in the history
  • Loading branch information
koush committed Apr 17, 2024
1 parent f5fabfe commit b7a8f97
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 14 deletions.
4 changes: 2 additions & 2 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 22 additions & 12 deletions server/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,33 +631,43 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
}

setupPluginHostAutoRestart(pluginHost: PluginHost) {
const logger = this.getDeviceLogger(this.findPluginDevice(pluginHost.pluginId));

let timeout: NodeJS.Timeout;

const restart = () => {
if (pluginHost.killed)
if (timeout)
return;

const t = 60000;
pluginHost.kill();
const timeout = 60000;
console.error(`plugin unexpectedly exited, restarting in ${timeout}ms`, pluginHost.pluginId);
setTimeout(async () => {
const existing = this.plugins[pluginHost.pluginId];
if (existing !== pluginHost) {
console.log('scheduled plugin restart cancelled, plugin was restarted by user', pluginHost.pluginId);
return;
}
logger.log('e', `plugin ${pluginHost.pluginId} unexpectedly exited, restarting in ${t}ms`);

timeout = setTimeout(async () => {
timeout = undefined;
const plugin = await this.datastore.tryGet(Plugin, pluginHost.pluginId);
if (!plugin) {
console.log('scheduled plugin restart cancelled, plugin no longer exists', pluginHost.pluginId);
logger.log('w', `scheduled plugin restart cancelled, plugin no longer exists ${pluginHost.pluginId}`);
return;
}

const existing = this.plugins[pluginHost.pluginId];
if (existing !== pluginHost) {
logger.log('w', `scheduled plugin restart cancelled, plugin was restarted by user ${pluginHost.pluginId}`);
return;
}

try {
this.runPlugin(plugin);
}
catch (e) {
console.error('error restarting plugin', plugin._id, e);
logger.log('e', `error restarting plugin ${pluginHost.pluginId}`);
logger.log('e', e.toStrin());
restart();
}
}, timeout);
}, t);
};

pluginHost.worker.once('error', restart);
pluginHost.worker.once('exit', restart);
pluginHost.worker.once('close', restart);
Expand Down

0 comments on commit b7a8f97

Please sign in to comment.