diff --git a/examples/spawn.lua b/examples/spawn.lua new file mode 100644 index 0000000..9b6551a --- /dev/null +++ b/examples/spawn.lua @@ -0,0 +1,18 @@ +fds, err = ckb.pipe() +assert(err == nil) + +local callee_code = [[ +local m = arg[2] .. arg[3] +local inherited_fds, err = ckb.inherited_fds() +local n, err = ckb.write(inherited_fds[1], m) +ckb.close(inherited_fds[1]) +assert(n == 10) +local pid = ckb.process_id() +assert(pid == 1) +]] + +pid, err = ckb.spawn(0, 3, 0, 0, {"-e", callee_code, "hello", "world"}, {fds[2]}) +assert(err == nil) +local ret = ckb.read(fds[1], 10) +assert(ret == "helloworld") +ckb.wait(pid) diff --git a/lua-loader/lua-ckb.c b/lua-loader/lua-ckb.c index c74631b..bb760af 100644 --- a/lua-loader/lua-ckb.c +++ b/lua-loader/lua-ckb.c @@ -828,25 +828,23 @@ int lua_ckb_spawn(lua_State *L) { uint64_t place = fields[2].arg.u64; uint64_t bounds = fields[3].arg.u64; - size_t argv_len = lua_rawlen(L, -5); - const char **argv = malloc(argv_len); + size_t argv_len = lua_rawlen(L, 5); + const char **argv = malloc(argv_len * sizeof(char*)); for (int i = 0; i < argv_len; i++) { - lua_rawgeti(L, -5, i+1); + lua_rawgeti(L, 5, i+1); const char* s = lua_tostring(L, -1); argv[i] = s; lua_pop(L, 1); } - size_t ifds_len = lua_rawlen(L, -6); - uint64_t *ifds = malloc(ifds_len + 1); + size_t ifds_len = lua_rawlen(L, 6); + uint64_t *ifds = malloc((ifds_len + 1) * sizeof(uint64_t)); ifds[ifds_len] = 0; for (int i = 0; i < ifds_len; i++) { - lua_rawgeti(L, -6, i+1); + lua_rawgeti(L, 6, i+1); uint64_t n = lua_tointeger(L, -1); ifds[i] = n; lua_pop(L, 1); } - free(argv); - free(ifds); uint64_t pid = 0; spawn_args_t spgs = { .argc = argv_len, @@ -855,6 +853,8 @@ int lua_ckb_spawn(lua_State *L) { .inherited_fds = ifds, }; int err = ckb_spawn(index, source, place, bounds, &spgs); + free(argv); + free(ifds); if (err != 0) { lua_pushnil(L); lua_pushinteger(L, err); @@ -1011,6 +1011,8 @@ static const luaL_Reg ckb_syscall[] = { {"load_input_by_field", lua_ckb_load_input_by_field}, {"load_header_by_field", lua_ckb_load_header_by_field}, + {"spawn", lua_ckb_spawn}, + {"wait", lua_ckb_wait}, {"process_id", lua_ckb_process_id}, {"pipe", lua_ckb_pipe}, {"read", lua_ckb_read}, diff --git a/tests/test_cases/Makefile b/tests/test_cases/Makefile index d4f4a54..a717634 100644 --- a/tests/test_cases/Makefile +++ b/tests/test_cases/Makefile @@ -59,6 +59,9 @@ dylibtest: spawnexample: RUST_LOG=debug $(CKB-DEBUGGER) --max-cycles $(MAX-CYCLES) --tx-file spawn.json --cell-index 0 --cell-type input --script-group-type lock +spawn_lua: + RUST_LOG=debug $(CKB-DEBUGGER) --max-cycles $(MAX-CYCLES) --tx-file spawn_lua.json --cell-index 0 --cell-type input --script-group-type lock + lua-fs-util: ./lua-fs-pack-and-unpack.sh ./lua-fs-unpack-existing.sh @@ -69,9 +72,9 @@ all: $(call run_with_mocked_tx, test_ckbsyscalls.lua) $(call run, bn.lua) -ci-no-dylib: hello_world save-and-load-file-system-data partial_loading memory_leak lua-fs-util +ci-no-dylib: hello_world save-and-load-file-system-data partial_loading memory_leak lua-fs-util spawnexample spawn_lua -ci: hello_world save-and-load-file-system-data partial_loading memory_leak dylibtest lua-fs-util +ci: hello_world save-and-load-file-system-data partial_loading memory_leak dylibtest lua-fs-util spawnexample spawn_lua $(call run_ci, test_require.lua) $(call run_ci, test_loadfile.lua) $(call run_with_mocked_tx, test_ckbsyscalls.lua) diff --git a/tests/test_cases/spawn_lua.json b/tests/test_cases/spawn_lua.json new file mode 100644 index 0000000..4cba12a --- /dev/null +++ b/tests/test_cases/spawn_lua.json @@ -0,0 +1,119 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000002", + "index": "0x0" + } + }, + "output": { + "capacity": "0x10000000", + "lock": { + "code_hash": "0x{{ hash ../../build/lua-loader }}", + "hash_type": "data2", + "args": "0x0000{{hash ../../examples/spawn.lua}}04" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data2", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../../build/lua-loader }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "index": "0x1" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data2", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../../examples/spawn.lua }}", + "header": null + } + ], + "header_deps": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "index": "0x1" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000002", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x0", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data2", + "args": "0x" + }, + "type": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data2", + "args": "0x" + } + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x" + ] + } +}