static void LuaIO_process_onexit(uv_process_t* handle, int64_t status, int signal) { if (handle->data) { LuaIO_process_data_t* data = handle->data; fprintf(stderr, "process[%d] exit. status: %" PRId64 ", signal: %d, file: %s\n", handle->pid, status, signal, data->options->args[1]); data->options->file = LuaIO_process_exepath_ptr; data->options->args[0] = LuaIO_process_exepath_ptr; uv_process_t* process = (uv_process_t*) LuaIO_malloc(sizeof(uv_process_t)); if (!process) { LuaIO_process_free_options(data->options); luaL_unref(LuaIO_get_main_thread(), LUA_REGISTRYINDEX, data->options_ref); LuaIO_free(data); fprintf(stderr, "process[%s] restart failed. no more memory for process\n", data->options->args[1]); } LuaIO_memzero(process, sizeof(uv_process_t)); process->data = data; int ret = uv_spawn(uv_default_loop(), process, data->options); if (ret < 0) { LuaIO_process_free_options(data->options); luaL_unref(LuaIO_get_main_thread(), LUA_REGISTRYINDEX, data->options_ref); LuaIO_free(data); uv_close((uv_handle_t*)process, NULL); fprintf(stderr, "process[%s] restart failed. uv_spawn() error: %s\n", data->options->args[1], uv_strerror(ret)); } if (data->cpu >= 0) LuaIO_set_affinity(process->pid, data->cpu); return; } fprintf(stderr, "process[%d] exit. status: %" PRId64 ", signal: %d\n", handle->pid, status, signal); uv_close((uv_handle_t*)handle, NULL); }
static int LuaIO_process_exec(lua_State* L) { const char* cmd; if (lua_type(L, 1) == LUA_TSTRING) { cmd = lua_tostring(L, 1); } else { return luaL_argerror(L, 2, "process.exec(cmd) error: cmd is required and must be [string]\n"); } /*shell, -c, cmd, null*/ char** args = LuaIO_malloc(sizeof(char*) * 4); args[0] = "/bin/sh"; args[1] = "-c"; args[2] = (char*)cmd; args[3] = NULL; if (!LuaIO_process_stdio_ptr) { LuaIO_process_stdio[0].flags = UV_INHERIT_FD; LuaIO_process_stdio[0].data.fd = 0; LuaIO_process_stdio[1].flags = UV_INHERIT_FD; LuaIO_process_stdio[1].data.fd = 1; LuaIO_process_stdio[2].flags = UV_INHERIT_FD; LuaIO_process_stdio[2].data.fd = 2; LuaIO_process_stdio_ptr = LuaIO_process_stdio; } uv_process_options_t* options = LuaIO_malloc(sizeof(uv_process_options_t)); if (!options) { LuaIO_free(args); return luaL_error(L, "process.exec(cmd) error: no memory for uv_process_options_t options\n"); } LuaIO_memzero(options, sizeof(uv_process_options_t)); options->exit_cb = LuaIO_process_onexit; options->file = "/bin/sh"; options->args = args; options->stdio_count = 3; options->stdio = LuaIO_process_stdio_ptr; uv_process_t* handle = LuaIO_malloc(sizeof(uv_process_t)); if (!handle) { LuaIO_process_free_options(options); return luaL_error(L, "process.exec(cmd) error: no memory for uv_process_t handle\n"); } LuaIO_memzero(handle, sizeof(uv_process_t)); int ret = uv_spawn(uv_default_loop(), handle, options); if (ret < 0) { LuaIO_process_free_options(options); uv_close((uv_handle_t*)handle, NULL); return luaL_error(L, "process.exec(cmd) uv_spawn() error: %s\n", uv_strerror(ret)); } if (!LuaIO_process_signal_ptr) { uv_signal_init(uv_default_loop(), &LuaIO_process_signal); LuaIO_process_signal_ptr = &LuaIO_process_signal; uv_signal_start(LuaIO_process_signal_ptr, LuaIO_process_signal_callback, SIGQUIT); } lua_pushinteger(L, handle->pid); return 1; }
void LuaIO_timer_free(uv_timer_t* timer) { if (timer != NULL) { LuaIO_timer_t* LuaIO_timer = LuaIO_list_entry(timer, LuaIO_timer_t, timer); if (LuaIO_timer_pool.free_timers < LuaIO_timer_pool.max_free_timers) { LuaIO_list_insert_head(&LuaIO_timer->list, &(LuaIO_timer_pool.free_list)); LuaIO_timer_pool.free_timers++; } else { LuaIO_free(LuaIO_timer); } } }
void LuaIO_pool_free(LuaIO_pool_t* pool, void* p) { if (p != NULL) { LuaIO_pool_chunk_t* chunk = (LuaIO_pool_chunk_t*)((char*)p - sizeof(LuaIO_pool_chunk_t)); if (pool->free_chunks < pool->max_free_chunks) { LuaIO_list_insert_head(&chunk->list, &pool->free_list); pool->free_chunks++; } else { LuaIO_free(chunk); } } }
void LuaIO_pmemory__free(void *p) { if (p != NULL) { LuaIO_pool_chunk_t *chunk = (LuaIO_pool_chunk_t*)((char*)p - sizeof(LuaIO_pool_chunk_t)); if (chunk->magic == LUAIO_PMEMORY_MAGIC) { LuaIO_free(chunk); return; } assert(chunk->magic != LUAIO_POOL_MAGIC); assert(chunk->magic < LUAIO_PMEMORY_SLOT_SIZE); LuaIO_pool_free(&LuaIO_pmemory_slots[chunk->magic], p); } }
static int LuaIO_process_fork(lua_State* L) { if (lua_type(L, 1) != LUA_TTABLE) { return luaL_argerror(L, 1, "process.fork(options) error: options must be [table]\n"); } if (!LuaIO_process_exepath_ptr) { size_t length = sizeof(LuaIO_process_exepath); int err = uv_exepath(LuaIO_process_exepath, &length); if (err < 0) { return luaL_error(L, "process.fork(options) uv_exepath() error: %s\n", uv_strerror(err)); } LuaIO_process_exepath_ptr = LuaIO_process_exepath; } lua_getfield(L, 1, "file"); const char* file; if (lua_type(L, -1) == LUA_TSTRING) { file = lua_tostring(L, -1); } else { return luaL_argerror(L, 2, "process.fork(options) error: options.file is required and must be [string]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "args"); size_t args_length = 0; char** args = NULL; if (lua_type(L, -1) == LUA_TTABLE) { args_length = lua_rawlen(L, -1); /*execpath, file, null => args_length + 3*/ args = LuaIO_malloc(sizeof(char*) * (args_length + 3)); if (!args) { return luaL_error(L, "process.fork(options) error: no memory for args\n"); } for (size_t i = 1; i <= args_length; ++i) { lua_rawgeti(L, -1, i); args[i + 1] = (char*)luaL_checkstring(L, -1); lua_pop(L, 1); } } else if (lua_type(L, -1) == LUA_TNIL) { /*execpath, file, null => args_length + 3*/ args = LuaIO_malloc(sizeof(char*) * 3); if (!args) { return luaL_error(L, "process.fork(options) error: no memory for args\n"); } } else { return luaL_argerror(L, 2, "process.fork(options) error: options.args must be [table]\n"); } lua_pop(L, 1); args[0] = LuaIO_process_exepath_ptr; args[1] = (char*)file; args[args_length + 2] = NULL; if (!LuaIO_process_stdio_ptr) { LuaIO_process_stdio[0].flags = UV_INHERIT_FD; LuaIO_process_stdio[0].data.fd = 0; LuaIO_process_stdio[1].flags = UV_INHERIT_FD; LuaIO_process_stdio[1].data.fd = 1; LuaIO_process_stdio[2].flags = UV_INHERIT_FD; LuaIO_process_stdio[2].data.fd = 2; LuaIO_process_stdio_ptr = LuaIO_process_stdio; } uv_process_options_t* options = LuaIO_malloc(sizeof(uv_process_options_t)); if (!options) { LuaIO_free(args); return luaL_error(L, "process.fork(options) error: no memory for uv_process_options_t options\n"); } LuaIO_memzero(options, sizeof(uv_process_options_t)); options->exit_cb = LuaIO_process_onexit; options->file = LuaIO_process_exepath_ptr; options->args = args; options->stdio_count = 3; options->stdio = LuaIO_process_stdio_ptr; lua_getfield(L, 1, "uid"); if (lua_type(L, -1) == LUA_TNUMBER) { options->uid = lua_tointeger(L, -1); options->flags |= UV_PROCESS_SETUID; } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.uid must be [number]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "gid"); if (lua_type(L, -1) == LUA_TNUMBER) { options->gid = lua_tointeger(L, -1); options->flags |= UV_PROCESS_SETGID; } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.gid must be [number]\n"); } lua_pop(L, 1); lua_getfield(L, 1, "detached"); if (lua_toboolean(L, -1)) { options->flags |= UV_PROCESS_DETACHED; } lua_pop(L, 1); lua_getfield(L, 1, "forever"); int forever = lua_toboolean(L, -1); lua_pop(L, 1); int cpu = -1; lua_getfield(L, 1, "cpu"); if (lua_type(L, -1) == LUA_TNUMBER) { cpu = lua_tointeger(L, -1); } else if (lua_type(L, -1) != LUA_TNIL) { LuaIO_process_free_options(options); return luaL_argerror(L, 2, "process.fork(options) error: options.cpu must be [number]\n"); } lua_pop(L, 1); uv_process_t* handle = LuaIO_malloc(sizeof(uv_process_t)); if (!handle) { LuaIO_process_free_options(options); return luaL_error(L, "process.fork(options) error: no memory for uv_process_t handle.\n"); } LuaIO_memzero(handle, sizeof(uv_process_t)); LuaIO_process_data_t* data = NULL; if (forever) { data = LuaIO_malloc(sizeof(LuaIO_process_data_t)); if (!data) { LuaIO_process_free_options(options); return luaL_error(L, "process.fork(options) error:no memory for LuaIO_process_data_t data.\n"); } lua_pushvalue(L, 1); data->options_ref = luaL_ref(L, LUA_REGISTRYINDEX); data->options = options; data->cpu = cpu; handle->data = data; } int ret = uv_spawn(uv_default_loop(), handle, options); if (ret < 0) { LuaIO_process_free_options(options); luaL_unref(L, LUA_REGISTRYINDEX, data->options_ref); LuaIO_free(data); uv_close((uv_handle_t*)handle, NULL); return luaL_error(L, "process.fork(options) uv_spawn() error: %s\n", uv_strerror(ret)); } if (cpu >= 0) LuaIO_set_affinity(handle->pid, cpu); if (!LuaIO_process_signal_ptr) { uv_signal_init(uv_default_loop(), &LuaIO_process_signal); LuaIO_process_signal_ptr = &LuaIO_process_signal; uv_signal_start(LuaIO_process_signal_ptr, LuaIO_process_signal_callback, SIGQUIT); } lua_pushinteger(L, handle->pid); return 1; }
static void LuaIO_timer_onclose(uv_handle_t *handle) { LuaIO_timer_t *LuaIO_timer = container_of(handle, LuaIO_timer_t, timer); LuaIO_free(LuaIO_timer); }