-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
Copy pathplugin-host.ts
110 lines (98 loc) · 4.06 KB
/
plugin-host.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// *****************************************************************************
// Copyright (C) 2018 Red Hat, Inc. and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import '@theia/core/shared/reflect-metadata';
import { Container } from '@theia/core/shared/inversify';
import { ConnectionClosedError, RPCProtocol } from '../../common/rpc-protocol';
import { ProcessTerminatedMessage, ProcessTerminateMessage } from './hosted-plugin-protocol';
import { PluginHostRPC } from './plugin-host-rpc';
import pluginHostModule from './plugin-host-module';
console.log('PLUGIN_HOST(' + process.pid + ') starting instance');
// override exit() function, to do not allow plugin kill this node
process.exit = function (code?: number): void {
const err = new Error('An plugin call process.exit() and it was prevented.');
console.warn(err.stack);
} as (code?: number) => never;
// same for 'crash'(works only in electron)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const proc = process as any;
if (proc.crash) {
proc.crash = function (): void {
const err = new Error('An plugin call process.crash() and it was prevented.');
console.warn(err.stack);
};
}
process.on('uncaughtException', (err: Error) => {
console.error(err);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const unhandledPromises: Promise<any>[] = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
unhandledPromises.push(promise);
setTimeout(() => {
const index = unhandledPromises.indexOf(promise);
if (index >= 0) {
promise.catch(err => {
unhandledPromises.splice(index, 1);
if (terminating && (ConnectionClosedError.is(err) || ConnectionClosedError.is(reason))) {
// during termination it is expected that pending rpc request are rejected
return;
}
console.error(`Promise rejection not handled in one second: ${err} , reason: ${reason}`);
if (err && err.stack) {
console.error(`With stack trace: ${err.stack}`);
}
});
}
}, 1000);
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
process.on('rejectionHandled', (promise: Promise<any>) => {
const index = unhandledPromises.indexOf(promise);
if (index >= 0) {
unhandledPromises.splice(index, 1);
}
});
let terminating = false;
const container = new Container();
container.load(pluginHostModule);
const rpc: RPCProtocol = container.get(RPCProtocol);
const pluginHostRPC = container.get(PluginHostRPC);
process.on('message', async (message: string) => {
if (terminating) {
return;
}
try {
const msg = JSON.parse(message);
if (ProcessTerminateMessage.is(msg)) {
terminating = true;
if (msg.stopTimeout) {
await Promise.race([
pluginHostRPC.terminate(),
new Promise(resolve => setTimeout(resolve, msg.stopTimeout))
]);
} else {
await pluginHostRPC.terminate();
}
rpc.dispose();
if (process.send) {
process.send(JSON.stringify({ type: ProcessTerminatedMessage.TYPE }));
}
}
} catch (e) {
console.error(e);
}
});