✨ add subprocess.fork/kill
This commit is contained in:
parent
2337994b08
commit
bf9f0d6338
|
@ -62,7 +62,9 @@ private:
|
||||||
// subprocess
|
// subprocess
|
||||||
"__subprocess_popen",
|
"__subprocess_popen",
|
||||||
"__subprocess_pclose",
|
"__subprocess_pclose",
|
||||||
"__subprocess_read_stdout"
|
"__subprocess_read_stdout",
|
||||||
|
"__subprocess_fork",
|
||||||
|
"__subprocess_kill"
|
||||||
};
|
};
|
||||||
|
|
||||||
// file mapper for file -> index
|
// file mapper for file -> index
|
||||||
|
|
|
@ -9,8 +9,15 @@
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
linker::linker(): show_path_flag(false), this_file("") {
|
linker::linker(): show_path_flag(false), this_file("") {
|
||||||
|
const auto env_get_path = getenv("PATH");
|
||||||
|
if (!env_get_path) {
|
||||||
|
err.warn("link", "cannot get env \"PATH\".");
|
||||||
|
envpath = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto seperator = util::is_windows()? ';':':';
|
const auto seperator = util::is_windows()? ';':':';
|
||||||
const auto PATH = std::string(getenv("PATH"));
|
const auto PATH = std::string(env_get_path);
|
||||||
usize last = 0, position = PATH.find(seperator, 0);
|
usize last = 0, position = PATH.find(seperator, 0);
|
||||||
while(position!=std::string::npos) {
|
while(position!=std::string::npos) {
|
||||||
std::string dirpath = PATH.substr(last, position-last);
|
std::string dirpath = PATH.substr(last, position-last);
|
||||||
|
|
|
@ -4,9 +4,17 @@
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define popen _popen
|
#define popen _popen
|
||||||
#define pclose _pclose
|
#define pclose _pclose
|
||||||
|
#define perror _perror
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -59,10 +67,114 @@ var builtin_subprocess_read_stdout(context* ctx, gc* ngc) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var builtin_subprocess_fork(context* ctx, gc* ngc) {
|
||||||
|
auto cmd = ctx->localr[1];
|
||||||
|
if (!cmd.is_vec()) {
|
||||||
|
return nas_err("subprocess::fork", "expect a string as the command");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// STARTUPINFO si;
|
||||||
|
// PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
// // init STARTUPINFO
|
||||||
|
// ZeroMemory(&si, sizeof(si));
|
||||||
|
// si.cb = sizeof(si);
|
||||||
|
// si.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
|
// si.wShowWindow = SW_SHOW;
|
||||||
|
|
||||||
|
// // init PROCESS_INFORMATION
|
||||||
|
// ZeroMemory(&pi, sizeof(pi));
|
||||||
|
|
||||||
|
// auto len = MultiByteToWideChar(CP_UTF8, 0, cmd.str().c_str(), -1, nullptr, 0);
|
||||||
|
|
||||||
|
// auto res = CreateProcess(
|
||||||
|
// nullptr,
|
||||||
|
// cmd.str().c_str(),
|
||||||
|
// nullptr,
|
||||||
|
// nullptr,
|
||||||
|
// false,
|
||||||
|
// 0,
|
||||||
|
// nullptr,
|
||||||
|
// nullptr,
|
||||||
|
// &si,
|
||||||
|
// &pi
|
||||||
|
// );
|
||||||
|
#else
|
||||||
|
// create argv
|
||||||
|
char** argv = new char*[cmd.vec().elems.size()+1];
|
||||||
|
for(const auto& v : cmd.vec().elems) {
|
||||||
|
if (!v.is_str()) {
|
||||||
|
return nas_err("subprocess::fork", "non-string arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(usize i = 0; i<cmd.vec().elems.size(); ++i) {
|
||||||
|
argv[i] = strdup(cmd.vec().elems[i].str().c_str());
|
||||||
|
}
|
||||||
|
argv[cmd.vec().elems.size()] = nullptr;
|
||||||
|
|
||||||
|
// use the same env of parent process
|
||||||
|
char** env = nullptr;
|
||||||
|
if (getenv("PATH")) {
|
||||||
|
env = new char*[2];
|
||||||
|
env[0] = strdup((std::string("PATH=") + getenv("PATH")).c_str());
|
||||||
|
env[1] = nullptr;
|
||||||
|
} else {
|
||||||
|
env = new char*[1];
|
||||||
|
env[0] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create child process
|
||||||
|
auto pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
return nas_err("subprocess::fork", "failed to create sub-process");
|
||||||
|
}
|
||||||
|
// child process
|
||||||
|
if (pid==0) {
|
||||||
|
execve("nasal", argv, env);
|
||||||
|
_exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parent process
|
||||||
|
for(usize i = 0; argv[i]; ++i) {
|
||||||
|
delete argv[i];
|
||||||
|
}
|
||||||
|
delete[] argv;
|
||||||
|
for(usize i = 0; env[i]; ++i) {
|
||||||
|
delete env[i];
|
||||||
|
}
|
||||||
|
delete[] env;
|
||||||
|
return var::num(pid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builtin_subprocess_kill(context* ctx, gc* ngc) {
|
||||||
|
#ifdef WIN32
|
||||||
|
// TODO
|
||||||
|
#else
|
||||||
|
auto pid = ctx->localr[1];
|
||||||
|
if (!pid.is_num()) {
|
||||||
|
return nas_err("subprocess::kill", "need numeral pid");
|
||||||
|
}
|
||||||
|
|
||||||
|
int status;
|
||||||
|
pid_t result = waitpid(pid.num(), &status, WNOHANG);
|
||||||
|
// child process running
|
||||||
|
if (result==0) {
|
||||||
|
kill(pid.num(), SIGTERM);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
nasal_builtin_table subprocess_native[] = {
|
nasal_builtin_table subprocess_native[] = {
|
||||||
{"__subprocess_popen", builtin_subprocess_popen},
|
{"__subprocess_popen", builtin_subprocess_popen},
|
||||||
{"__subprocess_pclose", builtin_subprocess_pclose},
|
{"__subprocess_pclose", builtin_subprocess_pclose},
|
||||||
{"__subprocess_read_stdout", builtin_subprocess_read_stdout},
|
{"__subprocess_read_stdout", builtin_subprocess_read_stdout},
|
||||||
|
{"__subprocess_fork", builtin_subprocess_fork},
|
||||||
|
{"__subprocess_kill", builtin_subprocess_kill},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@ void subprocess_destructor(void*);
|
||||||
var builtin_subprocess_popen(context*, gc*);
|
var builtin_subprocess_popen(context*, gc*);
|
||||||
var builtin_subprocess_pclose(context*, gc*);
|
var builtin_subprocess_pclose(context*, gc*);
|
||||||
var builtin_subprocess_read_stdout(context*, gc*);
|
var builtin_subprocess_read_stdout(context*, gc*);
|
||||||
|
|
||||||
|
var builtin_subprocess_fork(context*, gc*);
|
||||||
|
var builtin_subprocess_kill(context*, gc*);
|
||||||
extern nasal_builtin_table subprocess_native[];
|
extern nasal_builtin_table subprocess_native[];
|
||||||
|
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ var dlopen = func(libname) {
|
||||||
if (io.exists(libname))
|
if (io.exists(libname))
|
||||||
return __dlopen(libname);
|
return __dlopen(libname);
|
||||||
# find dynamic lib through PATH
|
# find dynamic lib through PATH
|
||||||
var envpath = split(os.platform()=="windows"? ";":":",unix.getenv("PATH"));
|
var envpath = split(os.platform()=="windows"? ";":":", unix.getenv("PATH"));
|
||||||
# first find ./module
|
# first find ./module
|
||||||
append(envpath, ".");
|
append(envpath, ".");
|
||||||
var path = os.platform()=="windows"? "\\module\\":"/module/";
|
var path = os.platform()=="windows"? "\\module\\":"/module/";
|
||||||
|
|
|
@ -8,4 +8,12 @@ var pclose = func(subproc) {
|
||||||
|
|
||||||
var read = func(subproc) {
|
var read = func(subproc) {
|
||||||
return __subprocess_read_stdout(subproc);
|
return __subprocess_read_stdout(subproc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fork = func(vec) {
|
||||||
|
return __subprocess_fork(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
var kill = func(pid) {
|
||||||
|
return __subprocess_kill(pid);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue