Refactored subprocesses handling in bbb-webrtc-sfu

They should now restart when crashing and shouldnt be stuck anymore
This commit is contained in:
prlanzarin 2018-01-26 19:10:01 +00:00
parent 9b36199908
commit 6a9c610379
5 changed files with 137 additions and 57 deletions

View 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";
}
}

View File

@ -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

View File

@ -221,6 +221,3 @@ let logAvailableSessions = function() {
}
}
}
process.on('SIGTERM', stopAll);
process.on('SIGINT', stopAll);

View File

@ -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

View File

@ -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');