diff options
| author | ruki <[email protected]> | 2019-08-17 00:49:06 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-08-16 22:54:38 +0800 |
| commit | 1de49ce846981a065ce3bea73591b797718ae993 (patch) | |
| tree | 30f6332a3b94e112f7e8ef7e0c9d38e72e5dde81 /core/src | |
| parent | 3edf63549fd45db761e09452b9b1af2ce23ee751 (diff) | |
add subprocess
Diffstat (limited to 'core/src')
| m--------- | core/src/tbox/tbox | 0 | ||||
| -rw-r--r-- | core/src/xmake/machine.c | 35 | ||||
| -rw-r--r-- | core/src/xmake/makefile | 5 | ||||
| -rw-r--r-- | core/src/xmake/process/open.c | 22 | ||||
| -rw-r--r-- | core/src/xmake/process/openv.c | 25 | ||||
| -rw-r--r-- | core/src/xmake/process/prefix.h | 80 | ||||
| -rw-r--r-- | core/src/xmake/process/subprocess___tostring.c (renamed from core/src/xmake/process/close.c) | 35 | ||||
| -rw-r--r-- | core/src/xmake/process/subprocess_close___gc.c | 88 | ||||
| -rw-r--r-- | core/src/xmake/process/subprocess_wait.c (renamed from core/src/xmake/process/wait.c) | 27 | ||||
| -rw-r--r-- | core/src/xmake/process/waitlist.c | 17 |
10 files changed, 271 insertions, 63 deletions
diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox -Subproject 6df2a6b41f964e31ebdae5be49e3fb3ec2740fb +Subproject 0cdb41ee2f944466e4d69219922f2feb5b76151 diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c index 5e34d8fd5..84c286b09 100644 --- a/core/src/xmake/machine.c +++ b/core/src/xmake/machine.c @@ -94,7 +94,7 @@ tb_int_t xm_io_std(lua_State* lua); tb_int_t xm_io_open(lua_State* lua); tb_int_t xm_io_openlock(lua_State* lua); -// the file functions +// the io/file functions tb_int_t xm_io_file_read(lua_State* lua); tb_int_t xm_io_file_seek(lua_State* lua); tb_int_t xm_io_file_write(lua_State* lua); @@ -106,7 +106,7 @@ tb_int_t xm_io_file___len(lua_State* lua); tb_int_t xm_io_file___tostring(lua_State* lua); tb_int_t xm_io_file___gc(lua_State* lua); -// the filelock functions +// the io/filelock functions tb_int_t xm_io_filelock_path(lua_State* lua); tb_int_t xm_io_filelock_lock(lua_State* lua); tb_int_t xm_io_filelock_unlock(lua_State* lua); @@ -146,9 +146,13 @@ tb_int_t xm_string_startswith(lua_State* lua); // the process functions tb_int_t xm_process_open(lua_State* lua); tb_int_t xm_process_openv(lua_State* lua); -tb_int_t xm_process_wait(lua_State* lua); tb_int_t xm_process_waitlist(lua_State* lua); -tb_int_t xm_process_close(lua_State* lua); + +// the process/subprocess functions +tb_int_t xm_process_subprocess_wait(lua_State* lua); +tb_int_t xm_process_subprocess_close(lua_State* lua); +tb_int_t xm_process_subprocess___gc(lua_State* lua); +tb_int_t xm_process_subprocess___tostring(lua_State* lua); // the sandbox functions tb_int_t xm_sandbox_interactive(lua_State* lua); @@ -237,7 +241,7 @@ static luaL_Reg const g_io_functions[] = , { tb_null, tb_null } }; -// the file functions +// the io/file functions static luaL_Reg const g_io_file_functions[] = { { "read", xm_io_file_read } @@ -253,7 +257,7 @@ static luaL_Reg const g_io_file_functions[] = , { tb_null, tb_null } }; -// the filelock functions +// the io/filelock functions static luaL_Reg const g_io_filelock_functions[] = { { "path", xm_io_filelock_path } @@ -300,12 +304,20 @@ static luaL_Reg const g_process_functions[] = { { "open", xm_process_open } , { "openv", xm_process_openv } -, { "wait", xm_process_wait } , { "waitlist", xm_process_waitlist } -, { "close", xm_process_close } , { tb_null, tb_null } }; +// the process/subprocess functions +static luaL_Reg const g_process_subprocess_functions[] = +{ + { "close", xm_process_subprocess_close } +, { "wait", xm_process_subprocess_wait } +, { "__gc", xm_process_subprocess___gc } +, { "__tostring", xm_process_subprocess___tostring } +, { tb_null, tb_null } +}; + // the sandbox functions static luaL_Reg const g_sandbox_functions[] = { @@ -628,10 +640,10 @@ xm_machine_ref_t xm_machine_init() // bind io functions luaL_register(machine->lua, "io", g_io_functions); - // bind io.file (metatable) functions + // bind io._file (metatable) functions xm_machine_register_metatable(machine, "io", "_file", "io._file*", g_io_file_functions); - // bind io.filelock (metatable) functions + // bind io._filelock (metatable) functions xm_machine_register_metatable(machine, "io", "_filelock", "io._filelock*", g_io_filelock_functions); // add stdin, stdout, stderr to io @@ -649,6 +661,9 @@ xm_machine_ref_t xm_machine_init() // bind process functions luaL_register(machine->lua, "process", g_process_functions); + // bind process._subprocess (metatable) functions + xm_machine_register_metatable(machine, "process", "_subprocess", "process._subprocess*", g_process_subprocess_functions); + // bind sandbox functions luaL_register(machine->lua, "sandbox", g_sandbox_functions); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 7f8e5e4c5..af8d469d0 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -75,9 +75,10 @@ xmake_C_FILES += \ string/startswith \ process/open \ process/openv \ - process/wait \ process/waitlist \ - process/close \ + process/subprocess_wait \ + process/subprocess___tostring \ + process/subprocess_close___gc \ sandbox/interactive \ semver/parse \ semver/compare \ diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c index fad3e8fec..bbb78ad27 100644 --- a/core/src/xmake/process/open.c +++ b/core/src/xmake/process/open.c @@ -133,7 +133,27 @@ tb_int_t xm_process_open(lua_State* lua) // init process tb_process_ref_t process = (tb_process_ref_t)tb_process_init_cmd(command, &attr); - if (process) lua_pushlightuserdata(lua, (tb_pointer_t)process); + if (process) + { + // init subprocess + xm_subprocess_t* subprocess = xm_subprocess_new(lua); + subprocess->process = process; + subprocess->is_opened = tb_true; + + // attach subprocess + tb_process_priv_set(process, subprocess); + + // save subprocess name + tb_size_t name_maxn = tb_arrayn(subprocess->name); + tb_strlcpy(subprocess->name, "subprocess: ", name_maxn); + if (command_size < name_maxn - tb_arrayn("subprocess: ")) + tb_strcat(subprocess->name, command); + else + { + tb_strcat(subprocess->name, "..."); + tb_strcat(subprocess->name, command + (command_size - name_maxn + tb_arrayn("subprocess: ") + tb_arrayn("..."))); + } + } else lua_pushnil(lua); return 1; } diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c index 459a56832..0ff26988c 100644 --- a/core/src/xmake/process/openv.c +++ b/core/src/xmake/process/openv.c @@ -50,7 +50,8 @@ tb_int_t xm_process_openv(lua_State* lua) } // get shellname - tb_char_t const* shellname = lua_tostring(lua, 1); + size_t shellname_size = 0; + tb_char_t const* shellname = luaL_checklstring(lua, 1, &shellname_size); tb_check_return_val(shellname, 0); // get the arguments count @@ -175,7 +176,27 @@ tb_int_t xm_process_openv(lua_State* lua) // init process tb_process_ref_t process = (tb_process_ref_t)tb_process_init(shellname, argv, &attr); - if (process) lua_pushlightuserdata(lua, (tb_pointer_t)process); + if (process) + { + // init subprocess + xm_subprocess_t* subprocess = xm_subprocess_new(lua); + subprocess->process = process; + subprocess->is_opened = tb_true; + + // attach subprocess + tb_process_priv_set(process, subprocess); + + // save subprocess name + tb_size_t name_maxn = tb_arrayn(subprocess->name); + tb_strlcpy(subprocess->name, "subprocess: ", name_maxn); + if (shellname_size < name_maxn - tb_arrayn("subprocess: ")) + tb_strcat(subprocess->name, shellname); + else + { + tb_strcat(subprocess->name, "..."); + tb_strcat(subprocess->name, shellname + (shellname_size - name_maxn + tb_arrayn("subprocess: ") + tb_arrayn("..."))); + } + } else lua_pushnil(lua); // exit argv diff --git a/core/src/xmake/process/prefix.h b/core/src/xmake/process/prefix.h index becbb93e6..2b0fec706 100644 --- a/core/src/xmake/process/prefix.h +++ b/core/src/xmake/process/prefix.h @@ -1,7 +1,7 @@ /*!A cross-platform build utility based on Lua * * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * you may not use this subprocess except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -15,7 +15,7 @@ * Copyright (C) 2015 - 2019, TBOOX Open Source Group. * * @author ruki - * @file prefix.h + * @subprocess prefix.h * */ #ifndef XM_PROCESS_PREFIX_H @@ -26,6 +26,82 @@ */ #include "../prefix.h" +/* ////////////////////////////////////////////////////////////////////////////////////// + * macross + */ + +// the subprocess udata type +#define xm_subprocess_udata "process._subprocess*" + +// return lock success +#define xm_subprocess_return_success() do { return 1; } while (0) + +// return lock error with reason +#define xm_subprocess_return_error(lua, subprocess, reason) \ + do \ + { \ + lua_pushnil(lua); \ + lua_pushfstring(lua, "error: %s (%s)", reason, subprocess->name); \ + return 2; \ + } while (0) + +// return closed error +#define xm_subprocess_return_error_closed(lua) \ + do \ + { \ + lua_pushnil(lua); \ + lua_pushliteral(lua, "error: subprocess has been closed"); \ + return 2; \ + } while (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * types + */ + +// the subprocess type +typedef struct __xm_subprocess_t +{ + // the process reference + tb_process_ref_t process; + + // is opened? + tb_bool_t is_opened; + + // the process name + tb_char_t name[32]; + +} xm_subprocess_t; + +/* ////////////////////////////////////////////////////////////////////////////////////// + * interfaces + */ +static __tb_inline__ xm_subprocess_t* xm_subprocess_new(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, tb_null); + + // new subprocess + xm_subprocess_t* subprocess = (xm_subprocess_t*)lua_newuserdata(lua, sizeof(xm_subprocess_t)); + tb_assert_and_check_return_val(subprocess, tb_null); + + // init subprocess + luaL_getmetatable(lua, xm_subprocess_udata); + lua_setmetatable(lua, -2); + tb_memset(subprocess, 0, sizeof(xm_subprocess_t)); + return subprocess; +} + +static __tb_inline__ xm_subprocess_t* xm_subprocess_get(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, tb_null); + + // get subprocess + xm_subprocess_t* subprocess = (xm_subprocess_t*)luaL_checkudata(lua, 1, xm_subprocess_udata); + tb_assert(subprocess); + return subprocess; +} + #endif diff --git a/core/src/xmake/process/close.c b/core/src/xmake/process/subprocess___tostring.c index dc1a465a3..ab93455b0 100644 --- a/core/src/xmake/process/close.c +++ b/core/src/xmake/process/subprocess___tostring.c @@ -11,19 +11,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * Copyright (C) 2015 - 2019, TBOOX Open Source Group. * * @author ruki - * @file close.c + * @file subprocess___tostring.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ -#define TB_TRACE_MODULE_NAME "process.close" -#define TB_TRACE_MODULE_DEBUG (0) +#define TB_TRACE_MODULE_NAME "subprocess___tostring" +#define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes @@ -34,26 +34,17 @@ * implementation */ -// process.close(p) -tb_int_t xm_process_close(lua_State* lua) +/* + * tostring(subprocess) + */ +tb_int_t xm_process_subprocess___tostring(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); - // is user data? - if (!lua_isuserdata(lua, 1)) - return 0; - - // get the process - tb_process_ref_t process = (tb_process_ref_t)lua_touserdata(lua, 1); - tb_check_return_val(process, 0); - - // exit process - tb_process_exit(process); - - // save result: ok - lua_pushboolean(lua, tb_true); - - // ok - return 1; + // get subprocess name as string + xm_subprocess_t* subprocess = xm_subprocess_get(lua); + lua_pushstring(lua, subprocess->name); + xm_subprocess_return_success(); } + diff --git a/core/src/xmake/process/subprocess_close___gc.c b/core/src/xmake/process/subprocess_close___gc.c new file mode 100644 index 000000000..30c3f3656 --- /dev/null +++ b/core/src/xmake/process/subprocess_close___gc.c @@ -0,0 +1,88 @@ +/*!A cross-platform build utility based on Lua + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2019, TBOOX Open Source Group. + * + * @author ruki + * @file subprocess_close___gc.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "subprocess_close___gc" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +static tb_int_t xm_subprocess_close_impl(lua_State* lua, tb_bool_t allow_closed_subprocess) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // close subprocess + xm_subprocess_t* subprocess = xm_subprocess_get(lua); + if (!subprocess->is_opened) + { + if (allow_closed_subprocess) + { + lua_pushboolean(lua, tb_true); + xm_subprocess_return_success(); + } + else xm_subprocess_return_error_closed(lua); + } + + // check + tb_assert(subprocess->process); + + // close process + tb_process_exit(subprocess->process); + subprocess->process = tb_null; + subprocess->is_opened = tb_false; + + // mark this subprocess as closed + tb_strlcpy(subprocess->name, "subprocess: (closed subprocess)", tb_arrayn(subprocess->name)); + + // close ok + lua_pushboolean(lua, tb_true); + xm_subprocess_return_success(); +} + +/* ////////////////////////////////////////////////////////////////////////////////////// + * interfaces + */ + +/* + * subprocess:close() + */ +tb_int_t xm_process_subprocess_close(lua_State* lua) +{ + return xm_subprocess_close_impl(lua, tb_false); +} + +/* + * subprocess:close() + */ +tb_int_t xm_process_subprocess___gc(lua_State* lua) +{ + return xm_subprocess_close_impl(lua, tb_true); +} diff --git a/core/src/xmake/process/wait.c b/core/src/xmake/process/subprocess_wait.c index b20b81d74..c7cb82377 100644 --- a/core/src/xmake/process/wait.c +++ b/core/src/xmake/process/subprocess_wait.c @@ -15,14 +15,14 @@ * Copyright (C) 2015 - 2019, TBOOX Open Source Group. * * @author ruki - * @file wait.c + * @file subprocess_wait.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ -#define TB_TRACE_MODULE_NAME "process.wait" +#define TB_TRACE_MODULE_NAME "subprocess_wait" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// @@ -34,31 +34,24 @@ * implementation */ -// ok, status = process.wait(proc, timeout) -tb_int_t xm_process_wait(lua_State* lua) +// ok, status = subprocess:wait(timeout) +tb_int_t xm_process_subprocess_wait(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); - // is user data? - if (!lua_isuserdata(lua, 1)) - { - // error - lua_pushfstring(lua, "invalid argument type(%s) for process.wait", luaL_typename(lua, 1)); - lua_error(lua); - return 0; - } - - // get the process - tb_process_ref_t process = (tb_process_ref_t)lua_touserdata(lua, 1); - tb_check_return_val(process, 0); + // get subprocess + xm_subprocess_t* subprocess = xm_subprocess_get(lua); + if (!subprocess->is_opened) + xm_subprocess_return_error_closed(lua); + tb_assert(subprocess->process); // get the timeout tb_long_t timeout = (tb_long_t)luaL_checkinteger(lua, 2); // wait it tb_long_t status = 0; - tb_long_t ok = tb_process_wait(process, &status, timeout); + tb_long_t ok = tb_process_wait(subprocess->process, &status, timeout); // save result lua_pushinteger(lua, ok); diff --git a/core/src/xmake/process/waitlist.c b/core/src/xmake/process/waitlist.c index 2254f199f..98015c2d4 100644 --- a/core/src/xmake/process/waitlist.c +++ b/core/src/xmake/process/waitlist.c @@ -81,15 +81,15 @@ tb_int_t xm_process_waitlist(lua_State* lua) lua_pushinteger(lua, i + 1); lua_gettable(lua, 1); - // is userdata? - if (lua_isuserdata(lua, -1)) + // save this process + xm_subprocess_t* subprocess = (xm_subprocess_t*)luaL_checkudata(lua, -1, xm_subprocess_udata); + if (subprocess) { - // save this process - processes[i] = (tb_process_ref_t)lua_touserdata(lua, -1); - if (!processes[i]) + processes[i] = subprocess->process; + if (!subprocess->is_opened || !processes[i]) { // error - lua_pushfstring(lua, "process[%d] is null for process.waitlist", i); + lua_pushfstring(lua, "process[%d] is null or closed for process.waitlist", i); lua_error(lua); } } @@ -124,7 +124,10 @@ tb_int_t xm_process_waitlist(lua_State* lua) { // save one process info lua_newtable(lua); - lua_pushlightuserdata(lua, (tb_pointer_t)infolist[i].process); + tb_process_ref_t process = infolist[i].process; + if (process) + lua_pushlightuserdata(lua, tb_process_priv(process)); + else lua_pushnil(lua); lua_rawseti(lua, -2, 1); lua_pushinteger(lua, infolist[i].index + 1); lua_rawseti(lua, -2, 2); |
