Added server process cleanup.

Ylian Saint-Hilaire committed Jul 17, 2019 at 15:57 UTC 03e57916a8c4ca15003cc6073714ab2661f70cdb
5 files changed +43 -17
meshaccelerator.js
+4
@@ -17,6 +17,10 @@
17 const crypto = require('crypto');
18 var certStore = null;
19
20 +// When the parent process terminates, we exit also.
21 +process.on('disconnect', function () { process.exit(); });
22 +
23 +// Handle parent messages
24 process.on('message', function (message) {
25 switch (message.action) {
26 case 'sign': {
meshcentral.js
+32 -16
@@ -165,7 +165,7 @@ function CreateMeshCentralServer(config, args) {
165 }
166
167 // If "--launch" is in the arguments, launch now
168 - if (obj.args.launch == 1) {
168 + if (obj.args.launch) {
169 obj.StartEx();
170 } else {
171 // if "--launch" is not specified, launch the server as a child process.
@@ -183,20 +183,23 @@ function CreateMeshCentralServer(config, args) {
183
184 // Launch MeshCentral as a child server and monitor it.
185 obj.launchChildServer = function (startLine) {
186 + if (process.pid) { obj.updateServerState('monitor-pid', process.pid); }
187 + if (process.ppid) { obj.updateServerState('monitor-ppid', process.ppid); }
188 var child_process = require('child_process');
187 - var xprocess = child_process.exec(startLine + ' --launch', { maxBuffer: Infinity, cwd: obj.parentpath }, function (error, stdout, stderr) {
188 - if (xprocess.xrestart == 1) {
189 + childProcess = child_process.exec(startLine + ' --launch ' + process.pid, { maxBuffer: Infinity, cwd: obj.parentpath }, function (error, stdout, stderr) {
190 + if (childProcess.xrestart == 1) {
191 setTimeout(function () { obj.launchChildServer(startLine); }, 500); // This is an expected restart.
190 - } else if (xprocess.xrestart == 2) {
192 + } else if (childProcess.xrestart == 2) {
193 console.log('Expected exit...');
194 process.exit(); // User CTRL-C exit.
193 - } else if (xprocess.xrestart == 3) {
195 + } else if (childProcess.xrestart == 3) {
196 // Server self-update exit
197 var version = '';
198 if (typeof obj.args.selfupdate == 'string') { version = '@' + obj.args.selfupdate; }
199 var child_process = require('child_process');
200 var npmpath = ((typeof obj.args.npmpath == 'string') ? obj.args.npmpath : 'npm');
199 - var xxprocess = child_process.exec(npmpath + ' install meshcentral' + version, { maxBuffer: Infinity, cwd: obj.parentpath }, function (error, stdout, stderr) { });
201 + var npmproxy = ((typeof obj.args.npmproxy == 'string') ? (' --proxy ' + obj.args.npmproxy) : '');
202 + var xxprocess = child_process.exec(npmpath + npmproxy + ' install meshcentral' + version, { maxBuffer: Infinity, cwd: obj.parentpath }, function (error, stdout, stderr) { });
203 xxprocess.data = '';
204 xxprocess.stdout.on('data', function (data) { xxprocess.data += data; });
205 xxprocess.stderr.on('data', function (data) { xxprocess.data += data; });
@@ -229,8 +232,8 @@ function CreateMeshCentralServer(config, args) {
232 }
233 }
234 });
232 - xprocess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { xprocess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { xprocess.xrestart = 3; } else if (data.indexOf('Server restart...') >= 0) { xprocess.xrestart = 1; } console.log(data); });
233 - xprocess.stderr.on('data', function (data) {
235 + childProcess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { childProcess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { childProcess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { childProcess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { childProcess.xrestart = 3; } else if (data.indexOf('Server restart...') >= 0) { childProcess.xrestart = 1; } console.log(data); });
236 + childProcess.stderr.on('data', function (data) {
237 if (data.startsWith('le.challenges[tls-sni-01].loopback')) { return; } // Ignore this error output from GreenLock
238 if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); }
239 try {
@@ -239,7 +242,7 @@ function CreateMeshCentralServer(config, args) {
242 obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' ---- ' + obj.currentVer + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n');
243 } catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
244 });
242 - xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
245 + childProcess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
246 };
247
248 // Get current and latest MeshCentral server versions using NPM
@@ -249,13 +252,14 @@ function CreateMeshCentralServer(config, args) {
252 if (typeof obj.args.selfupdate == 'string') { callback(obj.currentVer, obj.args.selfupdate); return; } // If we are targetting a specific version, return that one as current.
253 var child_process = require('child_process');
254 var npmpath = ((typeof obj.args.npmpath == 'string') ? obj.args.npmpath : 'npm');
252 - var xprocess = child_process.exec(npmpath + ' view meshcentral dist-tags.latest', { maxBuffer: 512000, cwd: obj.parentpath }, function (error, stdout, stderr) { });
253 - xprocess.data = '';
254 - xprocess.stdout.on('data', function (data) { xprocess.data += data; });
255 - xprocess.stderr.on('data', function (data) { });
256 - xprocess.on('close', function (code) {
255 + var npmproxy = ((typeof obj.args.npmproxy == 'string') ? (' --proxy ' + obj.args.npmproxy) : '');
256 + var xxprocess = child_process.exec(npmpath + npmproxy + ' view meshcentral dist-tags.latest', { maxBuffer: 512000, cwd: obj.parentpath }, function (error, stdout, stderr) { });
257 + xxprocess.data = '';
258 + xxprocess.stdout.on('data', function (data) { xxprocess.data += data; });
259 + xxprocess.stderr.on('data', function (data) { });
260 + xxprocess.on('close', function (code) {
261 var latestVer = null;
258 - if (code == 0) { try { latestVer = xprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
262 + if (code == 0) { try { latestVer = xxprocess.data.split(' ').join('').split('\r').join('').split('\n').join(''); } catch (e) { } }
263 callback(obj.currentVer, latestVer);
264 });
265 } catch (ex) { callback(obj.currentVer, null, ex); } // If the system is running out of memory, an exception here can easily happen.
@@ -551,7 +555,7 @@ function CreateMeshCentralServer(config, args) {
555 );
556 };
557
554 - // Time to start the server or real.
558 + // Time to start the server of real.
559 obj.StartEx1b = function () {
560 var i;
561
@@ -563,6 +567,8 @@ function CreateMeshCentralServer(config, args) {
567
568 // Write the server state
569 obj.updateServerState('state', 'starting');
570 + if (process.pid) { obj.updateServerState('server-pid', process.pid); }
571 + if (process.ppid) { obj.updateServerState('server-ppid', process.ppid); }
572
573 // Start memory tracking if requested
574 if (typeof obj.args.memorytracking == 'number') {
@@ -1780,6 +1786,7 @@ process.on('SIGINT', function () { if (meshserver != null) { meshserver.Stop();
1786
1787 // Load the really basic modules
1788 var meshserver = null;
1789 +var childProcess = null;
1790 var previouslyInstalledModules = { };
1791 function mainStart() {
1792 // Check the NodeJS is version 6 or better.
@@ -1837,6 +1844,15 @@ function mainStart() {
1844
1845 // Install any missing modules and launch the server
1846 InstallModules(modules, function () { meshserver = CreateMeshCentralServer(config, args); meshserver.Start(); });
1847 +
1848 + // On exit, also terminate the child process if applicable
1849 + process.on("exit", function () { if (childProcess) { childProcess.kill(); childProcess = null; } });
1850 +
1851 + // If our parent exits, we also exit
1852 + process.stderr.on('end', function () { process.exit(); });
1853 + process.stdout.on('end', function () { process.exit(); });
1854 + process.stdin.on('end', function () { process.exit(); });
1855 + process.stdin.on('data', function (data) { });
1856 });
1857 }
1858
meshuser.js
+4
@@ -614,6 +614,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
614 parent.parent.performServerUpdate();
615 break;
616 }
617 + case 'print': {
618 + console.log(cmdargs["_"][0]);
619 + break;
620 + }
621 case 'updatecheck': {
622 parent.parent.getLatestServerVersion(function (currentVer, newVer, error) {
623 var r2 = 'Current Version: ' + currentVer + '\r\n';
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.3.7-x",
3 + "version": "0.3.7-y",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
sample-config.json
+2
@@ -25,6 +25,8 @@
25 "_AgentPong": 60,
26 "_AgentIdleTimeout": 150,
27 "_MeshErrorLogPath": "c:\\tmp",
28 + "_NpmPath": "c:\\npm.exe",
29 + "_NpmProxy": "http://1.2.3.4:80",
30 "_AllowHighQualityDesktop": true,
31 "_UserAllowedIP": "127.0.0.1,192.168.1.0/24",
32 "_UserBlockedIP": "127.0.0.1,::1,192.168.0.100",