@@ -32,15 +32,15 @@ export class IpcMain {
32
32
public readonly onMessage = this . _onMessage . event
33
33
private readonly _onDispose = new Emitter < NodeJS . Signals | undefined > ( )
34
34
public readonly onDispose = this . _onDispose . event
35
- public readonly exit : ( code ?: number ) => never
35
+ public readonly processExit : ( code ?: number ) => never
36
36
37
37
public constructor ( public readonly parentPid ?: number ) {
38
38
process . on ( "SIGINT" , ( ) => this . _onDispose . emit ( "SIGINT" ) )
39
39
process . on ( "SIGTERM" , ( ) => this . _onDispose . emit ( "SIGTERM" ) )
40
40
process . on ( "exit" , ( ) => this . _onDispose . emit ( undefined ) )
41
41
42
42
// Ensure we control when the process exits.
43
- this . exit = process . exit
43
+ this . processExit = process . exit
44
44
process . exit = function ( code ?: number ) {
45
45
logger . warn ( `process.exit() was prevented: ${ code || "unknown code" } .` )
46
46
} as ( code ?: number ) => never
@@ -71,6 +71,14 @@ export class IpcMain {
71
71
}
72
72
}
73
73
74
+ public exit ( error ?: number | ProcessError ) : never {
75
+ if ( error && typeof error !== "number" ) {
76
+ this . processExit ( typeof error . code === "number" ? error . code : 1 )
77
+ } else {
78
+ this . processExit ( error )
79
+ }
80
+ }
81
+
74
82
public handshake ( child ?: cp . ChildProcess ) : Promise < void > {
75
83
return new Promise ( ( resolve , reject ) => {
76
84
const target = child || process
@@ -161,28 +169,37 @@ export class WrapperProcess {
161
169
}
162
170
} )
163
171
164
- ipcMain ( ) . onMessage ( async ( message ) => {
172
+ ipcMain ( ) . onMessage ( ( message ) => {
165
173
switch ( message . type ) {
166
174
case "relaunch" :
167
175
logger . info ( `Relaunching: ${ this . currentVersion } -> ${ message . version } ` )
168
176
this . currentVersion = message . version
169
- this . started = undefined
170
- if ( this . process ) {
171
- this . process . removeAllListeners ( )
172
- this . process . kill ( )
173
- }
174
- try {
175
- await this . start ( )
176
- } catch ( error ) {
177
- logger . error ( error . message )
178
- ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
179
- }
177
+ this . relaunch ( )
180
178
break
181
179
default :
182
180
logger . error ( `Unrecognized message ${ message } ` )
183
181
break
184
182
}
185
183
} )
184
+
185
+ process . on ( "SIGUSR1" , async ( ) => {
186
+ logger . info ( "Received SIGUSR1; hotswapping" )
187
+ this . relaunch ( )
188
+ } )
189
+ }
190
+
191
+ private async relaunch ( ) : Promise < void > {
192
+ this . started = undefined
193
+ if ( this . process ) {
194
+ this . process . removeAllListeners ( )
195
+ this . process . kill ( )
196
+ }
197
+ try {
198
+ await this . start ( )
199
+ } catch ( error ) {
200
+ logger . error ( error . message )
201
+ ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
202
+ }
186
203
}
187
204
188
205
public start ( ) : Promise < void > {
@@ -244,13 +261,13 @@ export const wrap = (fn: () => Promise<void>): void => {
244
261
. then ( ( ) => fn ( ) )
245
262
. catch ( ( error : ProcessError ) : void => {
246
263
logger . error ( error . message )
247
- ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
264
+ ipcMain ( ) . exit ( error )
248
265
} )
249
266
} else {
250
267
const wrapper = new WrapperProcess ( require ( "../../package.json" ) . version )
251
268
wrapper . start ( ) . catch ( ( error ) => {
252
269
logger . error ( error . message )
253
- ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
270
+ ipcMain ( ) . exit ( error )
254
271
} )
255
272
}
256
273
}
0 commit comments