import { fromEvent , merge , Observable } from 'rxjs' ; import { take , share , mapTo , delay , tap } from 'rxjs/operators' ; import type { Logger } from 'src/core/server' ; interface IChild { kill : ( signal : string ) => Promise < void > ; } export function safeChildProcess ( logger , childProcess ) { const ownTerminateSignal$ = merge ( fromEvent ( process as NodeJS . EventEmitter , 'SIGTERM' ) . pipe ( mapTo ( 'SIGTERM' ) ) , fromEvent ( process as NodeJS . EventEmitter , 'SIGINT' ) . pipe ( mapTo ( 'SIGINT' ) ) , fromEvent ( process as NodeJS . EventEmitter , 'SIGBREAK' ) . pipe ( mapTo ( 'SIGBREAK' ) ) ) . pipe ( take ( 1 ) , share ( ) ) ; const ownTerminateMapToKill$ = ownTerminateSignal$ . pipe ( tap ( ( signal ) => { logger . debug ( `Kibana process received terminate signal: ${ signal }` ) ; } ) , mapTo ( 'SIGKILL' ) ) ; const kibanaForceExit$ = fromEvent ( process as NodeJS . EventEmitter , 'exit' ) . pipe ( take ( 1 ) , tap ( ( signal ) => { logger . debug ( `Kibana process forcefully exited with signal: ${ signal }` ) ; } ) , mapTo ( 'SIGKILL' ) ) ; const signalForChildProcess$ = merge ( ownTerminateMapToKill$ , kibanaForceExit$ ) ; const logAndKillChildProcess = tap ( ( signal ) => { logger . debug ( `Child process terminate signal was: ${ signal }. Closing the browser...` ) ; return childProcess . kill ( signal ) ; } ) ; const terminate$ = merge ( signalForChildProcess$ . pipe ( logAndKillChildProcess ) , ownTerminateSignal$ . pipe ( delay ( 1 ) , tap ( ( signal ) => { logger . debug ( `Kibana process terminate signal was: ${ signal }. Closing the browser...` ) ; return process . kill ( process . pid , signal ) ; } ) ) ) ; return { terminate$ } ; }