@@ -32,15 +32,15 @@ export class IpcMain {
3232 public readonly onMessage = this . _onMessage . event
3333 private readonly _onDispose = new Emitter < NodeJS . Signals | undefined > ( )
3434 public readonly onDispose = this . _onDispose . event
35- public readonly exit : ( code ?: number ) => never
35+ public readonly processExit : ( code ?: number ) => never
3636
3737 public constructor ( public readonly parentPid ?: number ) {
3838 process . on ( "SIGINT" , ( ) => this . _onDispose . emit ( "SIGINT" ) )
3939 process . on ( "SIGTERM" , ( ) => this . _onDispose . emit ( "SIGTERM" ) )
4040 process . on ( "exit" , ( ) => this . _onDispose . emit ( undefined ) )
4141
4242 // Ensure we control when the process exits.
43- this . exit = process . exit
43+ this . processExit = process . exit
4444 process . exit = function ( code ?: number ) {
4545 logger . warn ( `process.exit() was prevented: ${ code || "unknown code" } .` )
4646 } as ( code ?: number ) => never
@@ -71,6 +71,14 @@ export class IpcMain {
7171 }
7272 }
7373
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+
7482 public handshake ( child ?: cp . ChildProcess ) : Promise < void > {
7583 return new Promise ( ( resolve , reject ) => {
7684 const target = child || process
@@ -161,28 +169,37 @@ export class WrapperProcess {
161169 }
162170 } )
163171
164- ipcMain ( ) . onMessage ( async ( message ) => {
172+ ipcMain ( ) . onMessage ( ( message ) => {
165173 switch ( message . type ) {
166174 case "relaunch" :
167175 logger . info ( `Relaunching: ${ this . currentVersion } -> ${ message . version } ` )
168176 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 ( )
180178 break
181179 default :
182180 logger . error ( `Unrecognized message ${ message } ` )
183181 break
184182 }
185183 } )
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+ }
186203 }
187204
188205 public start ( ) : Promise < void > {
@@ -244,13 +261,13 @@ export const wrap = (fn: () => Promise<void>): void => {
244261 . then ( ( ) => fn ( ) )
245262 . catch ( ( error : ProcessError ) : void => {
246263 logger . error ( error . message )
247- ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
264+ ipcMain ( ) . exit ( error )
248265 } )
249266 } else {
250267 const wrapper = new WrapperProcess ( require ( "../../package.json" ) . version )
251268 wrapper . start ( ) . catch ( ( error ) => {
252269 logger . error ( error . message )
253- ipcMain ( ) . exit ( typeof error . code === "number" ? error . code : 1 )
270+ ipcMain ( ) . exit ( error )
254271 } )
255272 }
256273}
0 commit comments