Refactored subprocesses handling in bbb-webrtc-sfu
They should now restart when crashing and shouldnt be stuck anymore
This commit is contained in:
parent
9b36199908
commit
6a9c610379
116
labs/bbb-webrtc-sfu/lib/ProcessManager.js
Normal file
116
labs/bbb-webrtc-sfu/lib/ProcessManager.js
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Lucas Fialho Zawacki
|
||||
* Paulo Renato Lanzarin
|
||||
* (C) Copyright 2017 Bigbluebutton
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const cp = require('child_process');
|
||||
const Logger = require('./utils/Logger');
|
||||
const SCREENSHARE_PATH = './lib/screenshare/ScreenshareProcess';
|
||||
const VIDEO_PATH = './lib/video/VideoProcess.js';
|
||||
|
||||
module.exports = class ProcessManager {
|
||||
constructor() {
|
||||
this.screensharePid;
|
||||
this.videoPid;
|
||||
this.screenshareProcess;
|
||||
this.videoProcess;
|
||||
this.processes = {};
|
||||
this.runningState = "RUNNING";
|
||||
}
|
||||
|
||||
async start () {
|
||||
let screenshareProcess = this.startProcess(SCREENSHARE_PATH);
|
||||
|
||||
let videoProcess = this.startProcess(VIDEO_PATH);
|
||||
|
||||
this.processes[screenshareProcess.pid] = screenshareProcess;
|
||||
this.processes[videoProcess.pid] = videoProcess;
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
await this.finishChildProcesses();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
await this.finishChildProcesses();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', async (error) => {
|
||||
Logger.error('[ProcessManager] Uncaught exception', error.stack);
|
||||
await this.finishChildProcesses();
|
||||
process.exit('1');
|
||||
});
|
||||
|
||||
// Added this listener to identify unhandled promises, but we should start making
|
||||
// sense of those as we find them
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
Logger.error('[ProcessManager] Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
}
|
||||
|
||||
startProcess (processPath) {
|
||||
Logger.info("[ProcessManager] Starting process at path", processPath);
|
||||
let proc = cp.fork(processPath, {
|
||||
// Pass over all of the environment.
|
||||
env: process.ENV,
|
||||
// Share stdout/stderr, so we can hear the inevitable errors.
|
||||
silent: false
|
||||
});
|
||||
|
||||
proc.path = processPath;
|
||||
|
||||
proc.on('message', this.onMessage);
|
||||
proc.on('error', this.onError);
|
||||
|
||||
proc.on('disconnect', (error) => {
|
||||
Logger.info('[ProcessManager] Received disconnect event from child process with PID', this.pid, ', killing it');
|
||||
let processId = proc.pid;
|
||||
|
||||
proc.kill();
|
||||
if (this.runningState === 'RUNNING') {
|
||||
Logger.info('[ProcessManager] Restarting process', processId, 'because server is still running...');
|
||||
this.restartProcess(processId);
|
||||
}
|
||||
});
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
restartProcess (pid) {
|
||||
let process = this.processes[pid];
|
||||
if (typeof process !== 'undefined' && process) {
|
||||
let newProcess = this.startProcess(process.path);
|
||||
this.processes[newProcess.pid] = newProcess;
|
||||
delete this.processes[pid];
|
||||
}
|
||||
}
|
||||
|
||||
onMessage (message) {
|
||||
Logger.info('[ProcessManager] Received child message from', this.pid, message);
|
||||
}
|
||||
|
||||
onError (e) {
|
||||
Logger.error('[ProcessManager] Received child error', this.pid, e);
|
||||
}
|
||||
|
||||
onDisconnect (e) {
|
||||
}
|
||||
|
||||
async finishChildProcesses () {
|
||||
this.runningState = "STOPPING";
|
||||
|
||||
for (var process in this.processes) {
|
||||
let procObj = this.processes[process];
|
||||
if (procObj.kill === 'function' && !procObj.killed) {
|
||||
await procObj.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
this.runningState = "STOPPED";
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const ScreenshareManager = require('./ScreenshareManager');
|
||||
const Logger = require('../utils/Logger');
|
||||
const config = require('config');
|
||||
|
||||
|
||||
if (config.get('acceptSelfSignedCertificate')) {
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED=0;
|
||||
}
|
||||
@ -12,7 +15,11 @@ process.on('uncaughtException', (error) => {
|
||||
Logger.error('[ScreenshareProcess] Uncaught exception ', error.stack);
|
||||
});
|
||||
|
||||
process.on('disconnect', c.stopAll);
|
||||
process.on('disconnect', async () => {
|
||||
Logger.warn('[ScreenshareProcess] Parent process exited, cleaning things up and finishing child now...');
|
||||
await c.stopAll();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Added this listener to identify unhandled promises, but we should start making
|
||||
// sense of those as we find them
|
||||
|
@ -221,6 +221,3 @@ let logAvailableSessions = function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.on('SIGTERM', stopAll);
|
||||
process.on('SIGINT', stopAll);
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const Logger = require('../utils/Logger');
|
||||
const config = require('config');
|
||||
|
||||
@ -13,8 +15,11 @@ process.on('uncaughtException', (error) => {
|
||||
Logger.error('[VideoProcess] Uncaught exception ', error.stack);
|
||||
});
|
||||
|
||||
process.on('disconnect', () => {
|
||||
Logger.info("[VideoProcess] Parent process disconnected!");
|
||||
process.on('disconnect', async () => {
|
||||
Logger.warn('[VideoProcess] Parent process exited, cleaning things up and finishing child now...');
|
||||
//TODO below
|
||||
//async VideoManager.stopAll();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Added this listener to identify unhandled promises, but we should start making
|
||||
|
@ -5,64 +5,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const ConnectionManager = require('./lib/connection-manager/ConnectionManager');
|
||||
const HttpServer = require('./lib/connection-manager/HttpServer');
|
||||
const server = new HttpServer();
|
||||
const WebsocketConnectionManager = require('./lib/connection-manager/WebsocketConnectionManager');
|
||||
const cp = require('child_process');
|
||||
const Logger = require('./lib/utils/Logger');
|
||||
const ProcessManager = require('./lib/ProcessManager.js');
|
||||
const PM = new ProcessManager();
|
||||
|
||||
let screenshareProc = cp.fork('./lib/screenshare/ScreenshareProcess', {
|
||||
// Pass over all of the environment.
|
||||
env: process.ENV,
|
||||
// Share stdout/stderr, so we can hear the inevitable errors.
|
||||
silent: false
|
||||
});
|
||||
PM.start();
|
||||
|
||||
let videoProc = cp.fork('./lib/video/VideoProcess.js', {
|
||||
// Pass over all of the environment.
|
||||
env: process.ENV,
|
||||
// Share stdout/stderr, so we can hear the inevitable errors.
|
||||
silent: false
|
||||
});
|
||||
|
||||
let onMessage = function (message) {
|
||||
Logger.info('event','child message',this.pid,message);
|
||||
};
|
||||
|
||||
let onError = function(e) {
|
||||
Logger.error('event','child error',this.pid,e);
|
||||
};
|
||||
|
||||
let onDisconnect = function(e) {
|
||||
Logger.info(e);
|
||||
Logger.info('event','child disconnect',this.pid,'killing...');
|
||||
this.kill();
|
||||
};
|
||||
|
||||
screenshareProc.on('message',onMessage);
|
||||
screenshareProc.on('error',onError);
|
||||
screenshareProc.on('disconnect',onDisconnect);
|
||||
|
||||
videoProc.on('message',onMessage);
|
||||
videoProc.on('error',onError);
|
||||
videoProc.on('disconnect',onDisconnect);
|
||||
|
||||
process.on('SIGTERM', process.exit)
|
||||
process.on('SIGINT', process.exit)
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
Logger.error('[MainProcess] Uncaught exception', error.stack);
|
||||
process.exit('1');
|
||||
});
|
||||
|
||||
// Added this listener to identify unhandled promises, but we should start making
|
||||
// sense of those as we find them
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
Logger.error('[MainProcess] Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
const CM = new ConnectionManager(screenshareProc, videoProc);
|
||||
const CM = new ConnectionManager(PM.screenshareProcess, PM.videoProcess);
|
||||
|
||||
let websocketManager = new WebsocketConnectionManager(server.getServerObject(), '/bbb-webrtc-sfu');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user