1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

1. Fixed execv(e)

2. Fixed service.restart() for OpenRC
This commit is contained in:
Bryan Roe
2021-01-29 10:13:37 -08:00
parent 434cc0e66b
commit c3872d6ec8
4 changed files with 93 additions and 32 deletions

View File

@@ -595,7 +595,19 @@ duk_ret_t ILibDuktape_ChildProcess_execve(duk_context *ctx)
duk_pop(ctx); // [WCHAR_ARRAY][obj][array]
}
}
#ifndef WIN32
//
// We must close all open descriptors first, since the "new" process will have no idea about any that are still open
//
duk_eval_string(ctx, "require('util-descriptors').getOpenDescriptors();"); // [array]
while (duk_get_length(ctx, -1) > 0)
{
duk_array_pop(ctx, -1); // [array][fd]
close(duk_get_int(ctx, -1)); duk_pop(ctx); // [array]
}
execve(path, (char**)args, (char**)env);
return(ILibDuktape_Error(ctx, "_execve() returned error: %d ", errno));
#else

File diff suppressed because one or more lines are too long

View File

@@ -1553,17 +1553,27 @@ function serviceManager()
ret.stop.platform = platform;
ret.restart = function restart()
{
var child = require('child_process').execFile('/bin/sh', ['sh'], this.OpenRC ? { type: require('child_process').SpawnTypes.TERM } : null);
child.stdout.on('data', function (chunk) { });
if (restart.platform == 'upstart')
if (this.isMe() && this.OpenRC)
{
child.stdin.write('initctl restart ' + this.name + '\nexit\n');
// On OpenRC platforms, we cannot restart our own service using rc-service, so we must use execv
var args = this.parameters();
args.unshift(process.execPath);
require('child_process')._execve(process.execPath, args);
}
else
{
child.stdin.write('service ' + this.name + ' restart\nexit\n');
var child = require('child_process').execFile('/bin/sh', ['sh'], this.OpenRC ? { type: require('child_process').SpawnTypes.TERM } : null);
child.stdout.on('data', function (chunk) { });
if (restart.platform == 'upstart')
{
child.stdin.write('initctl restart ' + this.name + '\nexit\n');
}
else
{
child.stdin.write('service ' + this.name + ' restart\nexit\n');
}
child.waitExit();
}
child.waitExit();
};
ret.restart.platform = platform;
ret.status = function status()
@@ -1607,6 +1617,17 @@ function serviceManager()
child.waitExit();
return (parseInt(child.stdout.str.trim()));
}
ret.parameters = function()
{
var child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stderr.on('data', function () { });
child.stdin.write('cat ' + this.conf + ' | grep "^\\s*command_args=" | awk \'NR==1{ gsub(/^\\s*command_args=/,"",$0); print $0; }\'\nexit\n');
child.waitExit();
var val = JSON.parse(child.stdout.str.trim());
val = val.match(/(?:[^\s"]+|"[^"]*")+/g);
return (val);
}
}
ret.status.platform = platform;
}

View File

@@ -90,43 +90,71 @@ function getOpenDescriptors()
return ([]);
}
}
function closeDescriptors(fdArray, libc)
function closeDescriptors(fdArray)
{
var fd = null;
if (libc == null)
{
var libs = require('monitor-info').getLibInfo('libc');
while (libs.length > 0)
{
try
{
libc = require('_GenericMarshal').CreateNativeProxy(libs.shift().path);
libc.CreateMethod('close');
break;
}
catch (e)
{
libc = null;
}
}
if (libc == null) { throw ('cannot find libc'); }
}
if (this.libc == null) { throw ('cannot find libc'); }
while (fdArray.length > 0)
{
fd = fdArray.pop();
if (fd > 2)
{
libc.close(fd);
this.libc.close(fd);
}
}
}
function _execv(exePath, argarr)
{
if (this.libc == null)
{
throw ('cannot find libc');
}
var i;
var path = require('_GenericMarshal').CreateVariable(exePath);
var args = require('_GenericMarshal').CreateVariable((1 + argarr.length) * require('_GenericMarshal').PointerSize);
for (i = 0; i < argarr.length; ++i)
{
var arg = require('_GenericMarshal').CreateVariable(argarr[i]);
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
}
var fds = this.getOpenDescriptors();
this.closeDescriptors(fds);
this.libc.execv(path, args);
throw('exec error');
}
function getLibc()
{
var libs = require('monitor-info').getLibInfo('libc');
var libc = null;
while (libs.length > 0)
{
try
{
libc = require('_GenericMarshal').CreateNativeProxy(libs.pop().path);
libc.CreateMethod('execv');
libc.CreateMethod('close');
break;
}
catch (e)
{
libc = null;
continue;
}
}
return (libc);
}
switch (process.platform)
{
case 'linux':
case 'freebsd':
module.exports = { getOpenDescriptors: getOpenDescriptors, closeDescriptors: closeDescriptors };
module.exports = { getOpenDescriptors: getOpenDescriptors, closeDescriptors: closeDescriptors, _execv: _execv, libc: getLibc() };
break;
default:
module.exports = { getOpenDescriptors: invalid, closeDescriptors: invalid };