ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) { size_t i; ngx_int_t rc; u_char *err_msg; size_t len; u_char *data; #if (NGX_PCRE) ngx_pool_t *old_pool; #endif dd("nargs: %d", (int) nargs); dd("set Lua VM panic handler"); lua_atpanic(L, ngx_http_lua_atpanic); NGX_LUA_EXCEPTION_TRY { dd("initialize nginx context in Lua VM, code chunk at " "stack top sp = 1"); ngx_http_lua_set_by_lua_env(L, r, nargs, args); /* passing directive arguments to the user code */ for (i = 0; i < nargs; i++) { lua_pushlstring(L, (const char *) args[i].data, args[i].len); } #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ old_pool = ngx_http_lua_pcre_malloc_init(r->pool); #endif lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ dd("protected call user code"); rc = lua_pcall(L, nargs, 1, 1); dd("after protected call user code"); lua_remove(L, 1); /* remove traceback function */ #if (NGX_PCRE) /* XXX: work-around to nginx regex subsystem */ ngx_http_lua_pcre_malloc_done(old_pool); #endif if (rc != 0) { /* error occured when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { err_msg = (u_char *) "unknown reason"; len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to run set_by_lua*: %*s", len, err_msg); lua_settop(L, 0); /* clear remaining elems on stack */ return NGX_ERROR; } data = (u_char *) lua_tolstring(L, -1, &len); if (data) { val->data = ngx_palloc(r->pool, len); if (val->data == NULL) { return NGX_ERROR; } ngx_memcpy(val->data, data, len); val->len = len; } else { val->data = NULL; val->len = 0; } } NGX_LUA_EXCEPTION_CATCH { dd("nginx execution restored"); return NGX_ERROR; } /* clear Lua stack */ lua_settop(L, 0); return NGX_OK; }
static int lua_general_handler(mtev_dso_generic_t *self) { int status, rv; lua_general_conf_t *conf = get_config(self); lua_module_closure_t *lmc = pthread_getspecific(conf->key); mtev_lua_resume_info_t *ri = NULL; const char *err = NULL; char errbuf[128]; lua_State *L; if(!lmc) mtev_lua_general_init(self); lmc = pthread_getspecific(conf->key); if(!lmc || !conf || !conf->module || !conf->function) { goto boom; } ri = lua_general_new_resume_info(lmc); L = ri->coro_state; lua_getglobal(L, "require"); lua_pushstring(L, conf->module); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(nlerr, "lua: require %s failed\n", conf->module); mtev_lua_traceback(L); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(nlerr, "lua: %s\n", err); } } lua_pop(L,i); goto boom; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, conf->module); if(lua_isnil(L, -1)) { lua_pop(L, 1); snprintf(errbuf, sizeof(errbuf), "no such module: '%s'", conf->module); err = errbuf; goto boom; } lua_getfield(L, -1, conf->function); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); snprintf(errbuf, sizeof(errbuf), "no function '%s' in module '%s'", conf->function, conf->module); err = errbuf; goto boom; } status = lmc->resume(ri, 0); if(status == 0) return 0; /* If we've failed, resume has freed ri, so we should just return. */ mtevL(nlerr, "lua dispatch error: %d\n", status); tragic_failure(self); return 0; boom: if(err) mtevL(nlerr, "lua dispatch error: %s\n", err); if(ri) lua_general_ctx_free(ri); tragic_failure(self); return 0; }
bool CLuaArguments::Call ( CLuaMain* pLuaMain, const CLuaFunctionRef& iLuaFunction, CLuaArguments * returnValues ) const { assert ( pLuaMain ); TIMEUS startTime = GetTimeUs (); // Add the function name to the stack and get the event from the table lua_State* luaVM = pLuaMain->GetVirtualMachine (); assert ( luaVM ); LUA_CHECKSTACK ( luaVM, 1 ); int luaStackPointer = lua_gettop ( luaVM ); lua_getref ( luaVM, iLuaFunction.ToInt () ); // Push our arguments onto the stack PushArguments ( luaVM ); // Call the function with our arguments pLuaMain->ResetInstructionCount (); int iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 ); if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM ) { SString strRes = ConformResourcePath ( lua_tostring( luaVM, -1 ) ); vector <SString> vecSplit; strRes.Split ( ":", vecSplit ); if ( vecSplit.size ( ) >= 3 ) { SString strFile = vecSplit[0]; int iLine = atoi ( vecSplit[1].c_str ( ) ); SString strMsg = vecSplit[2].substr ( 1 ); g_pGame->GetScriptDebugging()->LogError ( strFile, iLine, strMsg ); } else g_pGame->GetScriptDebugging()->LogError ( luaVM, "%s", strRes.c_str () ); // cleanup the stack while ( lua_gettop ( luaVM ) - luaStackPointer > 0 ) lua_pop ( luaVM, 1 ); return false; // the function call failed } else { int iReturns = lua_gettop ( luaVM ) - luaStackPointer; if ( returnValues != NULL ) { for ( int i = - iReturns; i <= -1; i++ ) { returnValues->ReadArgument ( luaVM, i ); } } // cleanup the stack while ( lua_gettop ( luaVM ) - luaStackPointer > 0 ) lua_pop ( luaVM, 1 ); } CPerfStatLuaTiming::GetSingleton ()->UpdateLuaTiming ( pLuaMain, pLuaMain->GetFunctionTag ( iLuaFunction.m_iFunction ), GetTimeUs() - startTime ); return true; }
/***************************************************************************** * Called through lua_scripts_batch_execute to call 'probe' on * the script pointed by psz_filename. *****************************************************************************/ static int probe_luascript( vlc_object_t *p_this, const char * psz_filename, const luabatch_context_t *p_context ) { VLC_UNUSED(p_context); demux_t * p_demux = (demux_t *)p_this; p_demux->p_sys->psz_filename = strdup(psz_filename); /* Initialise Lua state structure */ lua_State *L = luaL_newstate(); if( !L ) { msg_Err( p_demux, "Could not create new Lua State" ); goto error; } p_demux->p_sys->L = L; /* Load Lua libraries */ luaL_openlibs( L ); /* FIXME: Don't open all the libs? */ vlclua_set_this( L, p_demux ); luaL_register( L, "vlc", p_reg ); luaopen_msg( L ); luaopen_strings( L ); luaopen_stream( L ); luaopen_variables( L ); luaopen_xml( L ); lua_pushstring( L, p_demux->psz_location ); lua_setfield( L, -2, "path" ); lua_pushstring( L, p_demux->psz_access ); lua_setfield( L, -2, "access" ); lua_pop( L, 1 ); /* Setup the module search path */ if( vlclua_add_modules_path( L, psz_filename ) ) { msg_Warn( p_demux, "Error while setting the module search path for %s", psz_filename ); goto error; } /* Load and run the script(s) */ if( vlclua_dofile( VLC_OBJECT(p_demux), L, psz_filename ) ) { msg_Warn( p_demux, "Error loading script %s: %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); goto error; } lua_getglobal( L, "probe" ); if( !lua_isfunction( L, -1 ) ) { msg_Warn( p_demux, "Error while running script %s, " "function probe() not found", psz_filename ); goto error; } if( lua_pcall( L, 0, 1, 0 ) ) { msg_Warn( p_demux, "Error while running script %s, " "function probe(): %s", psz_filename, lua_tostring( L, lua_gettop( L ) ) ); goto error; } if( lua_gettop( L ) ) { if( lua_toboolean( L, 1 ) ) { msg_Dbg( p_demux, "Lua playlist script %s's " "probe() function was successful", psz_filename ); lua_pop( L, 1 ); return VLC_SUCCESS; } } error: lua_pop( L, 1 ); lua_close( p_demux->p_sys->L ); p_demux->p_sys->L = NULL; FREENULL( p_demux->p_sys->psz_filename ); return VLC_EGENERIC; }
/*! Prepares a Lua state for, and catches errors from, CorsixTH_lua_main(). By executing in Lua mode as soon as possible, errors can be nicely caught sooner, hence this function does as little as possible and leaves the rest for CorsixTH_lua_main(). */ int main(int argc, char** argv) { struct compile_time_lua_check { // Lua 5.1, not 5.0, is required int lua_5_point_1_required[LUA_VERSION_NUM >= 501 ? 1 : -1]; // Lua numbers must be doubles so that the mantissa has at least // 32 bits (floats only have 24 bits) int number_is_double[types_equal<lua_Number, double>::result]; }; bool bRun = true; while(bRun) { lua_State *L = NULL; L = luaL_newstate(); if(L == NULL) { fprintf(stderr, "Fatal error starting CorsixTH: " "Cannot open Lua state.\n"); return 0; } lua_atpanic(L, CorsixTH_lua_panic); luaL_openlibs(L); lua_settop(L, 0); lua_pushcfunction(L, CorsixTH_lua_stacktrace); lua_pushcfunction(L, CorsixTH_lua_main); // Move command line parameters onto the Lua stack lua_checkstack(L, argc); for(int i = 0; i < argc; ++i) { lua_pushstring(L, argv[i]); } if(lua_pcall(L, argc, 0, 1) != 0) { const char* err = lua_tostring(L, -1); if(err != NULL) { fprintf(stderr, "%s\n", err); } else { fprintf(stderr, "An error has occured in CorsixTH:\n" "Uncaught non-string Lua error\n"); } lua_pushcfunction(L, Bootstrap_lua_error_report); lua_insert(L, -2); if(lua_pcall(L, 1, 0, 0) != 0) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); } } lua_getfield(L, LUA_REGISTRYINDEX, "_RESTART"); bRun = lua_toboolean(L, -1) != 0; // Get cleanup functions out of the Lua state (but don't run them yet) std::stack<void(*)(void)> stkCleanup; lua_getfield(L, LUA_REGISTRYINDEX, "_CLEANUP"); if(lua_type(L, -1) == LUA_TTABLE) { for(unsigned int i = 1; i <= lua_objlen(L, -1); ++i) { lua_rawgeti(L, -1, (int)i); stkCleanup.push((void(*)(void))lua_touserdata(L, -1)); lua_pop(L, 1); } } lua_close(L); // The cleanup functions are executed _after_ the Lua state is fully // closed, and in reserve order to that in which they were registered. while(!stkCleanup.empty()) { if(stkCleanup.top() != NULL) stkCleanup.top()(); stkCleanup.pop(); } if(bRun) { printf("Restarting...\n"); } } return 0; }
bool Settings::load() { auto L = m_state; bool has_settings = PlatformInterface::fileExists(SETTINGS_PATH); bool errors = luaL_loadfile(L, has_settings ? SETTINGS_PATH : DEFAULT_SETTINGS_PATH) != LUA_OK; errors = errors || lua_pcall(L, 0, 0, 0) != LUA_OK; if (errors) { Lumix::g_log_error.log("Editor") << SETTINGS_PATH << ": " << lua_tostring(L, -1); lua_pop(L, 1); return false; } if (lua_getglobal(L, "window") == LUA_TTABLE) { m_window.x = getIntegerField(L, "x", 0); m_window.y = getIntegerField(L, "y", 0); m_window.w = getIntegerField(L, "w", -1); m_window.h = getIntegerField(L, "h", -1); } lua_pop(L, 1); loadStyle(L); m_is_maximized = getBoolean(L, "maximized", true); m_is_opened = getBoolean(L, "settings_opened", false); m_is_asset_browser_opened = getBoolean(L, "asset_browser_opened", false); m_is_entity_list_opened = getBoolean(L, "entity_list_opened", false); m_is_entity_template_list_opened = getBoolean(L, "entity_template_list_opened", false); m_is_log_opened = getBoolean(L, "log_opened", false); m_is_profiler_opened = getBoolean(L, "profiler_opened", false); m_is_properties_opened = getBoolean(L, "properties_opened", false); m_is_crash_reporting_enabled = getBoolean(L, "error_reporting_enabled", true); Lumix::enableCrashReporting(m_is_crash_reporting_enabled && !m_force_no_crash_report); m_mouse_sensitivity_x = getFloat(L, "mouse_sensitivity_x", 200.0f); m_mouse_sensitivity_y = getFloat(L, "mouse_sensitivity_y", 200.0f); if (!m_editor->getEngine().getPatchFileDevice()) { if (lua_getglobal(L, "data_dir") == LUA_TSTRING) Lumix::copyString(m_data_dir, lua_tostring(L, -1)); lua_pop(L, 1); m_editor->getEngine().setPatchPath(m_data_dir); } auto& actions = m_app.getActions(); if (lua_getglobal(L, "actions") == LUA_TTABLE) { for (int i = 0; i < actions.size(); ++i) { if (lua_getfield(L, -1, actions[i]->name) == LUA_TTABLE) { for (int j = 0; j < Lumix::lengthOf(actions[i]->shortcut); ++j) { if (lua_rawgeti(L, -1, 1 + j) == LUA_TNUMBER) { actions[i]->shortcut[j] = (int)lua_tointeger(L, -1); } lua_pop(L, 1); } } lua_pop(L, 1); } } lua_pop(L, 1); m_app.getToolbarActions().clear(); if (lua_getglobal(L, "toolbar") == LUA_TTABLE) { int len = (int)lua_rawlen(L, -1); for (int i = 0; i < len; ++i) { if (lua_rawgeti(L, -1, i + 1) == LUA_TSTRING) { const char* action_name = lua_tostring(L, -1); Action* action = m_app.getAction(action_name); if(action) m_app.getToolbarActions().push(action); } lua_pop(L, 1); } } lua_pop(L, 1); ImGui::LoadDock(L); return true; }
bool compiled_chunk::run(lua_State* L) const { chunks_it_ = chunks_.begin(); if(lua_load(L, chunk_reader, reinterpret_cast<void*>(const_cast<compiled_chunk*>(this)), NULL, NULL) || lua_pcall(L, 0, 0, 0)) { const char* a = lua_tostring(L, -1); std::cerr << a << "\n"; lua_pop(L, 1); return true; } return false; }
const std::vector<std::string> unit_advancements_aspect::get_advancements(const unit_map::const_iterator& unit) const { if(!unit.valid()) { return std::vector<std::string>(); } const std::string& unit_id = (*unit).id(); const int unit_x = (*unit).get_location().x + 1; const int unit_y = (*unit).get_location().y + 1; LOG_LUA << "Entering unit_advancements_aspect::get_advancements() in instance " << this << " with unit " << unit_id << " on (x,y) = (" << unit_x << ", " << unit_y << ")\n"; if(L_ == NULL || ref_ == LUA_REFNIL) { //If we end up here, most likely the aspect don't use the lua-engine. //Just to make sure: if (val_ == "Lua Function") { return std::vector<std::string>(); } return utils::split(val_); } //put the Pointer back on the Stack lua_rawgeti(L_, LUA_REGISTRYINDEX, ref_); if(lua_isstring(L_, -1)) { return utils::split(lua_tostring(L_, -1)); } if(!lua_isfunction(L_, -1)) { ERR_LUA << "Can't evaluate advancement aspect: Value is neither a string nor a function." << std::endl; return std::vector<std::string>(); } //push parameter to the stack lua_pushinteger(L_, unit_x); lua_pushinteger(L_, unit_y); //To make unit_id a Parameter of the Lua function: //lua_pushfstring(L_, unit_id.c_str()); //call function if(lua_pcall(L_, 2, 1, 0) != 0) { ERR_LUA << "LUA Error while evaluating advancements_aspect: " << lua_tostring(L_, -1) << std::endl; return std::vector<std::string>(); } if (!lua_isstring(L_, -1)) { ERR_LUA << "LUA Error while evaluating advancements_aspect: Function must return String " << std::endl; return std::vector<std::string>(); } //get result from Lua-Stack const std::string retval = std::string(lua_tostring(L_, -1)); lua_pop(L_, 1); LOG_LUA << "Called Lua advancement function. Result was: \"" << retval << "\".\n"; return utils::split(retval); }
int plugin_debug_con_handle_stmt(chassis *chas, network_mysqld_con *con, GString *s) { gsize i, j; GPtrArray *fields; GPtrArray *rows; GPtrArray *row; switch(s->str[NET_HEADER_SIZE]) { case COM_QUERY: fields = NULL; rows = NULL; row = NULL; /* support the basic commands sent by the mysql shell */ if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select @@version_comment limit 1"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("@@version_comment"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("MySQL Enterprise Agent")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select USER()"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("USER()"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("root")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else { MYSQL_FIELD *field = NULL; lua_State *L = chas->priv->sc->L; if (0 == luaL_loadstring(L, s->str + NET_HEADER_SIZE + 1) && 0 == lua_pcall(L, 0, 1, 0)) { /* let's see what is on the stack * - scalars are turned into strings * return "foo" * - 1-dim tables are turned into a single-row result-set * return { foo = "bar", baz = "foz" } * - 2-dim tables are turned into a multi-row result-set * return { { foo = "bar" }, { "foz" } } */ switch (lua_type(L, -1)) { case LUA_TTABLE: /* take the names from the fields */ fields = network_mysqld_proto_fielddefs_new(); lua_pushnil(L); while (lua_next(L, -2) != 0) { if (lua_istable(L, -1)) { /* 2-dim table * * we only only take the keys from the first row * afterwards we ignore them */ lua_pushnil(L); while (lua_next(L, -2) != 0) { if (!rows) { /* this is the 1st round, add the keys */ lua_table_key_to_mysql_field(L, fields); } if (!row) row = g_ptr_array_new(); if (lua_isboolean(L, -1)) { g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE")); } else if (lua_isnumber(L, -1)) { g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1))); } else { g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); } lua_pop(L, 1); /* pop the value, but keep the key on the stack */ } if (!rows) rows = g_ptr_array_new(); g_ptr_array_add(rows, row); row = NULL; } else { /* 1-dim table */ lua_table_key_to_mysql_field(L, fields); if (!row) row = g_ptr_array_new(); if (lua_isboolean(L, -1)) { g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE")); } else if (lua_isnumber(L, -1)) { g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1))); } else { g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); } } lua_pop(L, 1); /* pop the value, but keep the key on the stack */ } if (row) { /* in 1-dim we have to append the row to the result-set, * in 2-dim this is already done and row is NULL */ if (!rows) rows = g_ptr_array_new(); g_ptr_array_add(rows, row); } break; default: /* a scalar value */ fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("lua"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); g_ptr_array_add(rows, row); break; } lua_pop(L, 1); /* get rid of the result */ network_mysqld_con_send_resultset(con->client, fields, rows); } /* if we don't have fields for the resultset, we should have a * error-msg on the stack */ if (!fields) { size_t err_len = 0; const char *err; err = lua_tolstring(L, -1, &err_len); network_mysqld_con_send_error(con->client, err, err_len); lua_pop(L, 1); } } /* clean up */ if (fields) { network_mysqld_proto_fielddefs_free(fields); fields = NULL; } if (rows) { for (i = 0; i < rows->len; i++) { row = rows->pdata[i]; for (j = 0; j < row->len; j++) { g_free(row->pdata[j]); } g_ptr_array_free(row, TRUE); } g_ptr_array_free(rows, TRUE); rows = NULL; } break; case COM_QUIT: break; case COM_INIT_DB: network_mysqld_con_send_ok(con->client); break; default: network_mysqld_con_send_error(con->client, C("unknown COM_*")); break; } return 0; }
AgentLuaInterface::AgentLuaInterface(int ID, double posX, double posY, double posZ, Sector *sector, std::string filename) : Agent(ID, posX, posY, posZ, sector), destinationX(posX), destinationY(posY),speed(1), moving(false),gridmove(false),filename(filename), nofile(false),removed(false),L(NULL) { desc = "LUA"; //Output::Inst()->kprintf("%f,%f", posX, posY); Output::Inst()->addGraphicAgent(ID, -1,-1); //Setup up the LUA stack: L = luaL_newstate(); if(L == NULL) { Output::Inst()->kprintf("<b><font color=\"brown\">A new Agent cannot be initialized. Lua(%s) is out of memory, Killing simulation</font></b></>", LUA_VERSION); Output::KillSimulation.store(true); removed = true; } else { luaL_openlibs(L); // Register the path to the Rana specific lua modules lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string cur_path = lua_tostring(L, -1); std::string module_path = Output::Inst()->RanaDir; //Output::Inst()->kdebug(module_path.c_str()); module_path.append("/modules/?.lua"); //Output::Inst()->kdebug(module_path.c_str()); cur_path.append(";"); cur_path.append(module_path); cur_path.append(";"); cur_path.append(Output::Inst()->AgentPath); cur_path.append("?.lua"); lua_pop(L,1); lua_pushstring(L, cur_path.c_str()); lua_setfield(L,-2,"path"); lua_pop(L,1); //set the global values for the agent: lua_pushnumber(L,ID); lua_setglobal(L,"ID"); lua_pushnumber(L,posX); lua_setglobal(L,"PositionX"); lua_pushnumber(L,posY); lua_setglobal(L, "PositionY"); lua_pushnumber(L, Phys::getMacroFactor()*Phys::getTimeRes()); lua_setglobal(L, "STEP_RESOLUTION"); lua_pushnumber(L, Phys::getTimeRes()); lua_setglobal(L, "EVENT_RESOLUTION"); lua_pushnumber(L, macroFactorMultiple); lua_setglobal(L, "StepMultiple"); lua_pushnumber(L, Phys::getEnvX()); lua_setglobal(L, "ENV_WIDTH"); lua_pushnumber(L, Phys::getEnvY()); lua_setglobal(L, "ENV_HEIGHT"); lua_pushnumber(L, Phys::getEnvZ()); lua_setglobal(L, "ENV_DEPTH"); lua_pushnumber(L, destinationX); lua_setglobal(L, "DestinationX"); lua_pushnumber(L,destinationY); lua_setglobal(L, "DestinationY"); lua_pushnumber(L, speed); lua_setglobal(L, "Speed"); lua_pushboolean(L, moving); lua_setglobal(L, "Moving"); lua_pushboolean(L, gridmove); lua_setglobal(L, "GridMove"); lua_pushnumber(L, mass); lua_setglobal(L, "Mass"); lua_pushnumber(L, charge); lua_setglobal(L, "Charge"); lua_pushnumber(L, radius); lua_setglobal(L, "Radius"); lua_pushnumber(L, color.red); lua_setglobal(L, "ColorRed"); lua_pushnumber(L, color.green); lua_setglobal(L, "ColorGreen"); lua_pushnumber(L, color.blue); lua_setglobal(L, "ColorBlue"); lua_pushnumber(L, color.alpha); lua_setglobal(L, "ColorAlpha"); //lua_newtable(L); //lua_setglobal(L, "EventTable"); //Register all the API functions: //Interface. lua_register(L, "l_debug", l_debug); lua_register(L, "l_print", l_print); lua_register(L, "say", l_debug); lua_register(L, "shout", l_print); //Physics and generator. lua_register(L, "l_speedOfSound", l_speedOfSound); lua_register(L, "l_distance", l_distance); lua_register(L, "l_currentTime",l_currentTime); lua_register(L, "l_currentTimeS", l_currentTimeS); lua_register(L, "l_generateEventID", l_generateEventID); lua_register(L, "l_getMacroFactor", l_getMacroFactor); lua_register(L, "l_getTimeResolution", l_getTimeResolution); lua_register(L, "l_getMersenneFloat", l_getMersenneFloat); lua_register(L, "l_getRandomFloat", l_getMersenneFloat); lua_register(L, "l_getRandomInteger", l_getMersenneInteger); lua_register(L, "l_getMersenneInteger", l_getMersenneInteger); //Map and movement. lua_register(L, "l_getEnvironmentSize", l_getEnvironmentSize); lua_register(L, "l_modifyMap", l_modifyMap); lua_register(L, "l_checkMap", l_checkMap); lua_register(L, "l_checkMapAndChange", l_checkMapAndChange); lua_register(L, "l_radialMapScan", l_radialMapScan); lua_register(L, "l_radialMapColorScan", l_radialMapColorScan); lua_register(L, "l_checkPosition", l_checkPosition); lua_register(L, "l_updatePosition", l_updatePosition); lua_register(L, "l_addPosition", l_addPosition); lua_register(L, "l_checkCollision", l_checkCollision); lua_register(L, "l_checkCollisionRadial", l_checkCollisionRadial); lua_register(L, "l_gridMove", l_gridMove); lua_register(L, "l_getMaskRadial", l_getMaskRadial); lua_register(L, "l_radialCollisionScan", l_radialCollisionScan); lua_register(L, "l_initializeGrid", l_initializeGrid); lua_register(L, "l_getGridScale", l_getGridScale); lua_register(L, "l_updatePositionIfFree", l_updatePositionIfFree); //Shared values. lua_register(L, "l_getSharedNumber", l_getSharedNumber); lua_register(L, "l_addSharedNumber",l_addSharedNumber); lua_register(L, "l_getSharedString", l_getSharedString); lua_register(L, "l_addSharedString", l_addSharedString); //Simulation core. lua_register(L, "l_getAgentPath", l_getAgentPath); lua_register(L, "l_getAgentPath", l_getAgentPath); lua_register(L, "l_stopSimulation", l_stopSimulation); lua_register(L, "l_removeAgent", l_removeAgent); lua_register(L, "l_addAgent", l_addAgent); //Agent. lua_register(L, "l_emitEvent", l_emitEvent); lua_register(L, "l_addGroup", l_addGroup); lua_register(L, "l_removeGroup", l_removeGroup); lua_register(L, "l_setStepMultiplier", l_setMacroFactorMultipler); lua_register(L, "l_changeAgentColor", l_changeAgentColor); std::string auxLib = Output::Inst()->RanaDir; auxLib.append("/modules/auxiliary.lua"); std::string settingsPath = filename; settingsPath.erase(settingsPath.end()-4,settingsPath.end()); settingsPath.append("_settings.lua"); if(luaL_loadfile(L, auxLib.c_str()) || lua_pcall(L,0,0,0)) { Output::Inst()->kprintf("<font color=\"red\">error : %s <\font>", lua_tostring(L, -1)); nofile = true; Output::Inst()->kprintf("Lua Agent disabled\n"); } if(luaL_loadfile(L, filename.c_str() ) || lua_pcall(L,0,0,0)) { Output::Inst()->kprintf("<font color=\"red\">error : %s <\font>", lua_tostring(L, -1)); nofile = true; Output::Inst()->kprintf("Lua Agent disabled\n"); } //if(sector != NULL) //Output::Inst()->kdebug("I belong to sector %i", sector->getID()); getSyncData(); //Call the Initialization function for the agent lua_settop(L,0); } moveFactor = Phys::getMacroFactor() * Phys::getTimeRes(); }
int LuaStack::executeFunction(int handler, int numArgs, int numResults, const std::function<void(lua_State*,int)>& func) { if (pushFunctionByHandler(handler)) /* L: ... arg1 arg2 ... func */ { if (numArgs > 0) { lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */ } int functionIndex = -(numArgs + 1); if (!lua_isfunction(_state, functionIndex)) { CCLOG("value at stack [%d] is not function", functionIndex); lua_pop(_state, numArgs + 1); // remove function and arguments return 0; } int traceCallback = 0; lua_getglobal(_state, "__G__TRACKBACK__"); /* L: ... func arg1 arg2 ... G */ if (!lua_isfunction(_state, -1)) { lua_pop(_state, 1); /* L: ... func arg1 arg2 ... */ } else { lua_insert(_state, functionIndex - 1); /* L: ... G func arg1 arg2 ... */ traceCallback = functionIndex - 1; } int error = 0; ++_callFromLua; error = lua_pcall(_state, numArgs, numResults, traceCallback); /* L: ... [G] ret1 ret2 ... retResults*/ --_callFromLua; if (error) { if (traceCallback == 0) { CCLOG("[LUA ERROR] %s", lua_tostring(_state, - 1)); /* L: ... error */ lua_pop(_state, 1); // remove error message from stack } else /* L: ... G error */ { lua_pop(_state, 2); // remove __G__TRACKBACK__ and error message from stack } return 0; } // get return value,don't pass LUA_MULTRET to numResults, do { if (numResults <= 0 || nullptr == func) break; func(_state, numResults); } while (0); if (traceCallback) { lua_pop(_state, 1); // remove __G__TRACKBACK__ from stack /* L: ... */ } } return 1; }
int LuaStack::executeFunctionReturnArray(int handler,int numArgs,int numResults,__Array& resultArray) { int top = lua_gettop(_state); if (pushFunctionByHandler(handler)) /* L: ... arg1 arg2 ... func */ { if (numArgs > 0) { lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */ } int functionIndex = -(numArgs + 1); if (!lua_isfunction(_state, functionIndex)) { CCLOG("value at stack [%d] is not function", functionIndex); lua_pop(_state, numArgs + 1); // remove function and arguments lua_settop(_state,top); return 0; } int traceback = 0; lua_getglobal(_state, "__G__TRACKBACK__"); /* L: ... func arg1 arg2 ... G */ if (!lua_isfunction(_state, -1)) { lua_pop(_state, 1); /* L: ... func arg1 arg2 ... */ } else { lua_insert(_state, functionIndex - 1); /* L: ... G func arg1 arg2 ... */ traceback = functionIndex - 1; } int error = 0; ++_callFromLua; error = lua_pcall(_state, numArgs, numResults, traceback); /* L: ... [G] ret1 ret2 ... retResults*/ --_callFromLua; if (error) { if (traceback == 0) { CCLOG("[LUA ERROR] %s", lua_tostring(_state, - 1)); /* L: ... error */ lua_pop(_state, 1); // remove error message from stack } else /* L: ... G error */ { lua_pop(_state, 2); // remove __G__TRACKBACK__ and error message from stack } lua_settop(_state,top); return 0; } // get return value,don't pass LUA_MULTRET to numResults, if (numResults <= 0) { lua_settop(_state,top); return 0; } for (int i = 0 ; i < numResults; i++) { if (lua_type(_state, -1) == LUA_TBOOLEAN) { bool value = lua_toboolean(_state, -1); resultArray.addObject(Bool::create(value)) ; }else if (lua_type(_state, -1) == LUA_TNUMBER) { double value = lua_tonumber(_state, -1); resultArray.addObject(Double::create(value)); }else if (lua_type(_state, -1) == LUA_TSTRING) { const char* value = lua_tostring(_state, -1); resultArray.addObject(String::create(value)); }else{ resultArray.addObject(static_cast<Ref*>(tolua_tousertype(_state, -1, nullptr))); } // remove return value from stack lua_pop(_state, 1); /* L: ... [G] ret1 ret2 ... ret*/ } /* L: ... [G]*/ if (traceback) { lua_pop(_state, 1); // remove __G__TRACKBACK__ from stack /* L: ... */ } } lua_settop(_state,top); return 1; }
void server_destroy(client_t *client, const char *reason) { lua_pushliteral(L, "on_client_close"); lua_rawget(L, LUA_GLOBALSINDEX); lua_pushnumber(L, client_num(client)); lua_pushstring(L, reason); if (lua_pcall(L, 2, 0, 0) != 0) { fprintf(stderr, "error calling on_client_close: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); } // Quitmeldung senden if (client->is_gui_client) { packet_t packet; packet_init(&packet, PACKET_QUIT_MSG); packet_writeXX(&packet, reason, strlen(reason)); server_send_packet(&packet, client); } else { server_writeto(client, "connection terminated: ", 23); server_writeto(client, reason, strlen(reason)); server_writeto(client, "\r\n", 2); } // Kompressionsrest flushen server_flush_compression(client); // Rest rausschreiben (hier keine Fehlerbehandlung mehr, da eh egal). // Bei Filewritern muss nichts geschrieben werden, da deren Daten // immer direkt rausgeschrieben werden. if (!client->is_file_writer) evbuffer_write(client->out_buf, client->fd); evbuffer_free(client->in_buf); evbuffer_free(client->out_buf); free(client->kill_me); if (client->compress) deflateEnd(&client->strm); event_del(&client->rd_event); event_del(&client->wr_event); client->in_buf = NULL; client->out_buf = NULL; if (client->player) player_detach_client(client, client->player); assert(client->next == NULL); assert(client->prev == NULL); if (client->is_gui_client) { if (client->next_gui == client) { assert(client->prev_gui == client); guiclients = NULL; } else { client->next_gui->prev_gui = client->prev_gui; client->prev_gui->next_gui = client->next_gui; guiclients = client->next_gui; } } num_clients--; #ifndef NO_CONSOLE_CLIENT if (client->fd != STDIN_FILENO) #endif #ifdef WIN32 if (client->is_file_writer) { close(client->fd); } else { closesocket(client->fd); } #else close(client->fd); #endif }
client_t *server_accept(int fd, const char *address) { client_t *client = clients; for (int i = 0; i < MAXCLIENTS; i++, client++) { if (!CLIENT_USED(client)) goto found; } // write(fd, "no free slot\r\n", 14); fprintf(stderr, "cannot accept() new incoming connection: no free slot\n"); return NULL; found: memset(client, 0, sizeof(client_t)); client->fd = fd; // File Writer wird leicht unterschiedlich behandelt client->is_file_writer = strstr(address, "special:file") == address; // Non Blocking setzen #ifdef WIN32 DWORD notblock = 1; ioctlsocket(client->fd, FIONBIO, ¬block); #else if (fcntl(client->fd, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "cannot set accept()ed socket nonblocking: %s\n", strerror(errno)); return NULL; } #endif // Soll Verbindung angenommen werden? lua_pushliteral(L, "on_new_client"); lua_rawget(L, LUA_GLOBALSINDEX); lua_pushstring(L, address); if (lua_pcall(L, 1, 2, 0) != 0) { fprintf(stderr, "error calling on_new_client: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); return NULL; } if (!lua_toboolean(L, -2)) { size_t len; const char *msg = lua_tolstring(L, -1, &len); write(client->fd, msg, len); lua_pop(L, 2); return NULL; } lua_pop(L, 2); // Libevent aktivieren event_set(&client->rd_event, client->fd, EV_READ | EV_PERSIST, server_readable, client); event_set(&client->wr_event, client->fd, EV_WRITE , server_writable, client); client->in_buf = evbuffer_new(); client->out_buf = evbuffer_new(); client->compress = 0; client->kill_me = NULL; client->player = NULL; client->next = NULL; client->prev = NULL; client->is_gui_client = 0; client->next_gui = NULL; client->prev_gui = NULL; num_clients++; // Annehmen lua_pushliteral(L, "on_client_accepted"); lua_rawget(L, LUA_GLOBALSINDEX); lua_pushnumber(L, client_num(client)); lua_pushstring(L, address); if (lua_pcall(L, 2, 0, 0) != 0) { fprintf(stderr, "error calling on_client_accepted: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); } if (!client->is_file_writer) event_add(&client->rd_event, NULL); return client; }
int main(int argc, const char *argv[]) { WINDOW *wnd; // file char-table gcTable[enTile_Ground] = ' '; gcTable[enTile_Wall] = '#'; gcTable[enTile_Food] = '@'; gcTable[enTile_RedHeadUp] = '^'; gcTable[enTile_RedHeadRight] = '>'; gcTable[enTile_RedHeadDown] = 'v'; gcTable[enTile_RedHeadLeft] = '<'; gcTable[enTile_RedBody] = 'X'; gcTable[enTile_GreenHeadUp] = '^'; gcTable[enTile_GreenHeadRight] = '>'; gcTable[enTile_GreenHeadDown] = 'v'; gcTable[enTile_GreenHeadLeft] = '<'; gcTable[enTile_GreenBody] = 'O'; // init Lua L = lua_open(); luaL_openlibs(L); int error = luaL_loadbuffer(L, "dofile('./snake.lua')", sizeof("dofile('./snake.lua')"), "line") || lua_pcall(L, 0, 0, 0); if (error) { mvaddstr(0, 0, lua_tostring(L, -1)); } luaL_openlib(L, "mylib", myLib, 0); // initialize curses wnd = initscr(); start_color(); init_pair(1, COLOR_RED, COLOR_BLACK);// for red snake init_pair(2, COLOR_GREEN, COLOR_BLACK);// for green snake init_pair(3, COLOR_WHITE, COLOR_BLACK);// for system output cbreak(); noecho(); getmaxyx(wnd, g_max_x, g_max_y); clear(); refresh(); init_game(); broadcast(); while (gbGameOn) {//game loop //getch(); get_input(); update_game(); broadcast(); // sleep(500); } lua_close(L); endwin(); return 0; }
// Initializes a lua chisel bool sinsp_chisel::init_lua_chisel(chisel_desc &cd, string const &fpath) { lua_State* ls = lua_open(); if(ls == NULL) { return false; } luaL_openlibs(ls); // // Load our own lua libs // luaL_openlib(ls, "sysdig", ll_sysdig, 0); luaL_openlib(ls, "chisel", ll_chisel, 0); luaL_openlib(ls, "evt", ll_evt, 0); // // Add our chisel paths to package.path // for(vector<chiseldir_info>::const_iterator it = g_chisel_dirs->begin(); it != g_chisel_dirs->end(); ++it) { string path(it->m_dir); path += "?.lua"; add_lua_package_path(ls, path.c_str()); } // // Load the script // if(luaL_loadfile(ls, fpath.c_str()) || lua_pcall(ls, 0, 0, 0)) { goto failure; } // // Extract the description // lua_getglobal(ls, "description"); if(!lua_isstring(ls, -1)) { return parse_view_info(ls, &cd); } cd.m_description = lua_tostring(ls, -1); // // Extract the short description // lua_getglobal(ls, "short_description"); if(!lua_isstring(ls, -1)) { goto failure; } cd.m_shortdesc = lua_tostring(ls, -1); // // Extract the category // cd.m_category = ""; lua_getglobal(ls, "category"); if(lua_isstring(ls, -1)) { cd.m_category = lua_tostring(ls, -1); } // // Extract the hidden flag and skip the chisel if it's set // lua_getglobal(ls, "hidden"); if(lua_isboolean(ls, -1)) { int sares = lua_toboolean(ls, -1); if(sares) { goto failure; } } // // Extract the args // lua_getglobal(ls, "args"); if(lua_isnoneornil(ls, -1)) { goto failure; } try { parse_lua_chisel_args(ls, &cd); } catch(...) { goto failure; } return true; failure: lua_close(ls); return false; }
int ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata) { TSHttpTxn txnp = (TSHttpTxn)edata; lua_State *l; ts_lua_http_ctx *http_ctx; ts_lua_main_ctx *main_ctx; http_ctx = (ts_lua_http_ctx*)TSContDataGet(contp); main_ctx = http_ctx->mctx; l = http_ctx->lua; TSMutexLock(main_ctx->mutexp); switch (event) { case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: lua_getglobal(l, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE); if (lua_type(l, -1) == LUA_TFUNCTION) { if (lua_pcall(l, 0, 1, 0)) { fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1)); } } break; case TS_EVENT_HTTP_SEND_REQUEST_HDR: lua_getglobal(l, TS_LUA_FUNCTION_SEND_REQUEST); if (lua_type(l, -1) == LUA_TFUNCTION) { if (lua_pcall(l, 0, 1, 0)) { fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1)); } } break; case TS_EVENT_HTTP_READ_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_READ_RESPONSE); if (lua_type(l, -1) == LUA_TFUNCTION) { if (lua_pcall(l, 0, 1, 0)) { fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1)); } } break; case TS_EVENT_HTTP_SEND_RESPONSE_HDR: lua_getglobal(l, TS_LUA_FUNCTION_SEND_RESPONSE); if (lua_type(l, -1) == LUA_TFUNCTION) { if (lua_pcall(l, 0, 1, 0)) { fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1)); } } break; case TS_EVENT_HTTP_TXN_CLOSE: ts_lua_destroy_http_ctx(http_ctx); TSContDestroy(contp); break; default: break; } TSMutexUnlock(main_ctx->mutexp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; }
void sinsp_chisel::load(string cmdstr) { m_filename = cmdstr; trim(cmdstr); ifstream is; // // Try to open the file as is // if(!openfile(m_filename, &is)) { // // Try to add the .sc extension // if(!openfile(m_filename + ".sc", &is)) { if(!openfile(m_filename + ".lua", &is)) { throw sinsp_exception("can't open file " + m_filename); } } } // // Bring the file into a string // string docstr((istreambuf_iterator<char>(is)), istreambuf_iterator<char>()); #ifdef HAS_LUA_CHISELS // // Rewind the stream // is.seekg(0); // // Load the file // std::istreambuf_iterator<char> eos; std::string scriptstr(std::istreambuf_iterator<char>(is), eos); // // Open the script // m_ls = lua_open(); luaL_openlibs(m_ls); // // Load our own lua libs // luaL_openlib(m_ls, "sysdig", ll_sysdig, 0); luaL_openlib(m_ls, "chisel", ll_chisel, 0); luaL_openlib(m_ls, "evt", ll_evt, 0); // // Add our chisel paths to package.path // for(uint32_t j = 0; j < g_chisel_dirs->size(); j++) { string path(g_chisel_dirs->at(j).m_dir); path += "?.lua"; add_lua_package_path(m_ls, path.c_str()); } // // Load the script // if(luaL_loadstring(m_ls, scriptstr.c_str()) || lua_pcall(m_ls, 0, 0, 0)) { throw sinsp_exception("Failed to load chisel " + m_filename + ": " + lua_tostring(m_ls, -1)); } // // Allocate the chisel context for the script // m_lua_cinfo = new chiselinfo(m_inspector); // // Set the context globals // lua_pushlightuserdata(m_ls, this); lua_setglobal(m_ls, "sichisel"); // // Extract the args // lua_getglobal(m_ls, "args"); if(!lua_istable(m_ls, -1)) { throw sinsp_exception("Failed to load chisel " + m_filename + ": args table missing"); } try { parse_lua_chisel_args(m_ls, &m_lua_script_info); } catch(sinsp_exception& e) { throw e; } // // Check if the script has an on_event // lua_getglobal(m_ls, "on_event"); if(lua_isfunction(m_ls, -1)) { m_lua_has_handle_evt = true; lua_pop(m_ls, 1); } #endif is.close(); }
void sinsp_chisel::on_init() { // // Done with the arguments, call init() // lua_getglobal(m_ls, "on_init"); if(!lua_isfunction(m_ls, -1)) { // // No on_init. // That's ok. Just return. // return; } if(lua_pcall(m_ls, 0, 1, 0) != 0) { // // Exception running init // const char* lerr = lua_tostring(m_ls, -1); string err = m_filename + ": error in init(): " + lerr; throw sinsp_exception(err); } if(m_new_chisel_to_exec == "") { if(!lua_isboolean(m_ls, -1)) { throw sinsp_exception(m_filename + " chisel error: wrong init() return value."); } if(!lua_toboolean(m_ls, -1)) { throw sinsp_exception("init() for chisel " + m_filename + " failed."); } } lua_pop(m_ls, 1); // // If the chisel called chisel.exec(), free this chisel and load the new one // if(m_new_chisel_to_exec != "") { free_lua_chisel(); load(m_new_chisel_to_exec); m_new_chisel_to_exec = ""; string args; for(uint32_t j = 0; j < m_argvals.size(); j++) { if(m_argvals[j].find(" ") == string::npos) { args += m_argvals[j]; } else { args += string("'") + m_argvals[j] + "'"; } if(j < m_argvals.size() - 1) { args += " "; } } m_argvals.clear(); set_args(args); on_init(); } }
bool sinsp_chisel::run(sinsp_evt* evt) { #ifdef HAS_LUA_CHISELS string line; ASSERT(m_ls); // // Make the event available to the API // lua_pushlightuserdata(m_ls, evt); lua_setglobal(m_ls, "sievt"); // // If this is the first event, put the event pointer on the stack. // We assume that the event pointer will never change. // if(m_lua_is_first_evt) { first_event_inits(evt); } // // If there is a timeout callback, see if it's time to call it // do_timeout(evt); // // If there is a filter, run it // if(m_lua_cinfo->m_filter != NULL) { if(!m_lua_cinfo->m_filter->run(evt)) { return false; } } // // If the script has the on_event callback, call it // if(m_lua_has_handle_evt) { lua_getglobal(m_ls, "on_event"); if(lua_pcall(m_ls, 0, 1, 0) != 0) { throw sinsp_exception(m_filename + " chisel error: " + lua_tostring(m_ls, -1)); } int oeres = lua_toboolean(m_ls, -1); lua_pop(m_ls, 1); if(m_lua_cinfo->m_end_capture == true) { throw sinsp_capture_interrupt_exception(); } if(oeres == false) { return false; } } // // If the script has a formatter, run it // if(m_lua_cinfo->m_formatter != NULL) { if(m_lua_cinfo->m_formatter->tostring(evt, &line)) { cout << line << endl; } } return true; #endif }
ngx_int_t ngx_http_lua_set_by_chunk( lua_State *l, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs ) { size_t i; ngx_int_t rc; // set Lua VM panic handler lua_atpanic(l, ngx_http_lua_atpanic); // initialize nginx context in Lua VM, code chunk at stack top sp = 1 ngx_http_lua_set_by_lua_env(l, r, nargs, args); // passing directive arguments to the user code for(i = 0; i < nargs; ++i) { lua_pushlstring(l, (const char*)args[i].data, args[i].len); } // protected call user code rc = lua_pcall(l, nargs, 1, 0); if(rc) { // error occured when running loaded code const char *err_msg = lua_tostring(l, -1); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-error) %s", err_msg); lua_settop(l, 0); // clear remaining elems on stack assert(lua_gettop(l) == 0); return NGX_ERROR; } if(setjmp(ngx_http_lua_exception) == 0) { // try { size_t rlen; const char *rdata = lua_tolstring(l, -1, &rlen); if(rdata) { val->data = ngx_pcalloc(r->pool, rlen); if (val->data == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate result buffer!"); return NGX_ERROR; } ngx_memcpy(val->data, rdata, rlen); val->len = rlen; } else { val->data = NULL; val->len = 0; } } else { // } catch dd("NginX execution restored"); } // clear Lua stack lua_settop(l, 0); return NGX_OK; }
void sinsp_chisel::set_args(vector<pair<string, string>> args) { #ifdef HAS_LUA_CHISELS uint32_t j; uint32_t n_required_args = get_n_required_args(); uint32_t n_optional_args = get_n_optional_args(); ASSERT(m_ls); // // Validate the arguments // if(args.size() < n_required_args) { throw sinsp_exception("wrong number of parameters for chisel " + m_filename + ", " + to_string((long long int)n_required_args) + " required, " + to_string((long long int)args.size()) + " given"); } else if(args.size() > n_optional_args + n_required_args) { throw sinsp_exception("too many parameters for chisel " + m_filename + ", " + to_string((long long int)(n_required_args)) + " required, " + to_string((long long int)(n_optional_args)) + " optional, " + to_string((long long int)args.size()) + " given"); } // // Push the arguments // for(j = 0; j < args.size(); j++) { lua_getglobal(m_ls, "on_set_arg"); if(!lua_isfunction(m_ls, -1)) { lua_pop(m_ls, 1); throw sinsp_exception("chisel " + m_filename + " misses a set_arg() function."); } lua_pushstring(m_ls, args[j].first.c_str()); lua_pushstring(m_ls, args[j].second.c_str()); // // call get_info() // if(lua_pcall(m_ls, 2, 1, 0) != 0) { throw sinsp_exception(m_filename + " chisel error: " + lua_tostring(m_ls, -1)); } if(!lua_isboolean(m_ls, -1)) { throw sinsp_exception(m_filename + " chisel error: wrong set_arg() return value."); } int sares = lua_toboolean(m_ls, -1); if(!sares) { throw sinsp_exception("set_arg() for chisel " + m_filename + " failed."); } lua_pop(m_ls, 1); } #endif }
/* Initialize the scripting environment. * * 初始化脚本环境。 * * It is possible to call this function to reset the scripting environment * assuming that we call scriptingRelease() before. * * 这个函数也可以在 scriptingRelease() 执行之后使用,用于对脚本环境进行重置。 * * See scriptingReset() for more information. */ void scriptingInit(void) { // 创建一个新的 lua 环境 lua_State *lua = lua_open(); // 载入内置函数库 luaLoadLibraries(lua); // 屏蔽所有不想暴露给脚本环境的函数(目前只有 loadfile) luaRemoveUnsupportedFunctions(lua); /* Initialize a dictionary we use to map SHAs to scripts. * 创建一个字典,用于将 SHA 校验码映射到脚本 * This is useful for replication, as we need to replicate EVALSHA * as EVAL, so we need to remember the associated script. * 因为 Redis 目前复制脚本的方法是将 EVALSHA 转换成 EVAL 来进行的, * 所以程序需要保存和 SHA 校验值相对应的脚本。 */ server.lua_scripts = dictCreate(&shaScriptObjectDictType,NULL); /* Register the redis commands table and fields */ // 创建 table ,并以给定名称将 C 函数注册到表格上 lua_newtable(lua); /* 注册 redis.call */ lua_pushstring(lua,"call"); lua_pushcfunction(lua,luaRedisCallCommand); lua_settable(lua,-3); /* 注册 redis.pcall */ lua_pushstring(lua,"pcall"); lua_pushcfunction(lua,luaRedisPCallCommand); lua_settable(lua,-3); /* 注册 redis.log 和 log levels. */ lua_pushstring(lua,"log"); lua_pushcfunction(lua,luaLogCommand); lua_settable(lua,-3); lua_pushstring(lua,"LOG_DEBUG"); lua_pushnumber(lua,REDIS_DEBUG); lua_settable(lua,-3); lua_pushstring(lua,"LOG_VERBOSE"); lua_pushnumber(lua,REDIS_VERBOSE); lua_settable(lua,-3); lua_pushstring(lua,"LOG_NOTICE"); lua_pushnumber(lua,REDIS_NOTICE); lua_settable(lua,-3); lua_pushstring(lua,"LOG_WARNING"); lua_pushnumber(lua,REDIS_WARNING); lua_settable(lua,-3); /* 注册 redis.sha1hex */ lua_pushstring(lua, "sha1hex"); lua_pushcfunction(lua, luaRedisSha1hexCommand); lua_settable(lua, -3); /* 注册 redis.error_reply and redis.status_reply */ lua_pushstring(lua, "error_reply"); lua_pushcfunction(lua, luaRedisErrorReplyCommand); lua_settable(lua, -3); lua_pushstring(lua, "status_reply"); lua_pushcfunction(lua, luaRedisStatusReplyCommand); lua_settable(lua, -3); /* Finally set the table as 'redis' global var. */ // 将 table 设置为 redis 全局变量 lua_setglobal(lua,"redis"); /* Replace math.random and math.randomseed with our implementations. */ // 将 math.random 和 math.randomseed 设置为 Redis 实现 // 用于生成确定性的随机数 // (对于同一个 seed ,生成的随机序列总是相同) lua_getglobal(lua,"math"); lua_pushstring(lua,"random"); lua_pushcfunction(lua,redis_math_random); lua_settable(lua,-3); lua_pushstring(lua,"randomseed"); lua_pushcfunction(lua,redis_math_randomseed); lua_settable(lua,-3); lua_setglobal(lua,"math"); /* Add a helper funciton that we use to sort the multi bulk output of non * deterministic commands, when containing 'false' elements. * 用于对不确定性多个回复的输出进行排序 */ { char *compare_func = "function __redis__compare_helper(a,b)\n" " if a == false then a = '' end\n" " if b == false then b = '' end\n" " return a<b\n" "end\n"; luaL_loadbuffer(lua,compare_func,strlen(compare_func),"@cmp_func_def"); lua_pcall(lua,0,0,0); } /* Create the (non connected) client that we use to execute Redis commands * inside the Lua interpreter. * 创建一个无网络连接的伪客户端,用于执行 Lua 脚本中的命令 * Note: there is no need to create it again when this function is called * by scriptingReset(). */ if (server.lua_client == NULL) { server.lua_client = createClient(-1); server.lua_client->flags |= REDIS_LUA_CLIENT; } /* Lua beginners ofter don't use "local", this is likely to introduce * subtle bugs in their code. To prevent problems we protect accesses * to global variables. * * 为了避免全局变量被意外地修改,保护全局变量。 */ scriptingEnableGlobalsProtection(lua); // 将 lua 环境赋值到服务器变量 server.lua = lua; }
void evalGenericCommand(redisClient *c, int evalsha) { lua_State *lua = server.lua; char funcname[43]; long long numkeys; int delhook = 0; /* We want the same PRNG sequence at every call so that our PRNG is * not affected by external state. * * 在每次执行 EVAL 时重置随机 seed ,从而保证可以生成相同的随机序列。 */ redisSrand48(0); /* We set this flag to zero to remember that so far no random command * was called. This way we can allow the user to call commands like * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command * is called (otherwise the replication and AOF would end with non * deterministic sequences). * * Thanks to this flag we'll raise an error every time a write command * is called after a random command was used. * * 用两个变量,对命令进行检查 * 确保在调用随机命令之后,再调用写命令将出现错误 */ server.lua_random_dirty = 0; server.lua_write_dirty = 0; /* Get the number of arguments that are keys */ // 获取输入键的数量 if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK) return; // 对键的正确性做一个快速检查 if (numkeys > (c->argc - 3)) { addReplyError(c,"Number of keys can't be greater than number of args"); return; } /* We obtain the script SHA1, then check if this function is already * defined into the Lua state */ // 组合出函数的名字,例如 f_282297a0228f48cd3fc6a55de6316f31422f5d17 funcname[0] = 'f'; funcname[1] = '_'; if (!evalsha) { /* Hash the code if this is an EVAL call */ // 如果执行的是 EVAL 命令,那么计算脚本的 SHA1 校验和 sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr)); } else { // 如果执行的是 EVALSHA 命令,直接使用传入的 SHA1 值 /* We already have the SHA if it is a EVALSHA */ int j; char *sha = c->argv[1]->ptr; for (j = 0; j < 40; j++) funcname[j+2] = tolower(sha[j]); funcname[42] = '\0'; } /* Try to lookup the Lua function */ // 按名查找函数 lua_getglobal(lua, funcname); if (lua_isnil(lua,1)) { // 没找到脚本相应的脚本 lua_pop(lua,1); /* remove the nil from the stack */ /* Function not defined... let's define it if we have the * body of the funciton. If this is an EVALSHA call we can just * return an error. */ if (evalsha) { // 如果执行的是 EVALSHA ,返回脚本未找到错误 addReply(c, shared.noscripterr); return; } // 如果执行的是 EVAL ,那么创建并执行新函数,然后将代码添加到脚本字典中 if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) return; /* Now the following is guaranteed to return non nil */ lua_getglobal(lua, funcname); redisAssert(!lua_isnil(lua,1)); } /* Populate the argv and keys table accordingly to the arguments that * EVAL received. */ // 设置 KEYS 和 ARGV 全局变量到 Lua 环境 luaSetGlobalArray(lua,"KEYS",c->argv+3,numkeys); luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,c->argc-3-numkeys); /* Select the right DB in the context of the Lua client */ // 为 Lua 所属的(伪)客户端设置数据库 selectDb(server.lua_client,c->db->id); /* Set an hook in order to be able to stop the script execution if it * is running for too much time. * * 设置一个钩子,用于在运行时间过长时停止脚本的运作。 * * We set the hook only if the time limit is enabled as the hook will * make the Lua script execution slower. * * 只在开启了时间限制选项时使用钩子,因为它会拖慢脚本的运行速度。 */ // 调用客户端 server.lua_caller = c; // 脚本开始时间 server.lua_time_start = ustime()/1000; // 是否杀死脚本 server.lua_kill = 0; // 只在开启时间限制时使用钩子 if (server.lua_time_limit > 0 && server.masterhost == NULL) { lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000); delhook = 1; } /* At this point whatever this script was never seen before or if it was * already defined, we can call it. We have zero arguments and expect * a single return value. */ // 执行脚本(所属的函数) if (lua_pcall(lua,0,1,0)) { // 以下是脚本执行出错的代码。。。 // 删除钩子 if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */ // 脚本执行已超时 if (server.lua_timedout) { // 清除超时 FLAG server.lua_timedout = 0; /* Restore the readable handler that was unregistered when the * script timeout was detected. */ // 将超时钩子里删除的读事件重新加上 aeCreateFileEvent(server.el,c->fd,AE_READABLE, readQueryFromClient,c); } // 清空调用者 server.lua_caller = NULL; // 更新目标数据库 selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */ addReplyErrorFormat(c,"Error running script (call to %s): %s\n", funcname, lua_tostring(lua,-1)); // 弹出函数 lua_pop(lua,1); // 执行完整的废料回首循环(full garbage-collection cycle) lua_gc(lua,LUA_GCCOLLECT,0); // 返回 return; } // 以下是脚本执行成功时执行的代码。。。 // 删除钩子 if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */ // 清空超时 FLAG server.lua_timedout = 0; // 清空调用者 server.lua_caller = NULL; // 更新 DB selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */ // 将 Lua 回复转换成 Redis 回复 luaReplyToRedisReply(c,lua); // 执行 1 步渐进式 GC lua_gc(lua,LUA_GCSTEP,1); /* If we have slaves attached we want to replicate this command as * EVAL instead of EVALSHA. We do this also in the AOF as currently there * is no easy way to propagate a command in a different way in the AOF * and in the replication link. * * 如果有附属节点,那么使用 EVAL 而不是 EVALSHA 来传播脚本 * 因为目前还没有代码可以检测脚本是否已经传送到附属节点中 * * IMPROVEMENT POSSIBLE: * 1) Replicate this command as EVALSHA in the AOF. * 2) Remember what slave already received a given script, and replicate * the EVALSHA against this slaves when possible. */ // 如果执行的是 EVALSHA 命令 if (evalsha) { // 取出脚本代码体(body) robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr); redisAssertWithInfo(c,NULL,script != NULL); // 重写客户端命令为 EVAL rewriteClientCommandArgument(c,0, resetRefCount(createStringObject("EVAL",4))); rewriteClientCommandArgument(c,1,script); } }
static int _load_script(void) { int rc = SLURM_SUCCESS; struct stat st; lua_State *L_orig = L; if (stat(lua_script_path, &st) != 0) { if (L_orig) { (void) error("Unable to stat %s, " "using old script: %s", lua_script_path, strerror(errno)); return SLURM_SUCCESS; } return error("Unable to stat %s: %s", lua_script_path, strerror(errno)); } if (st.st_mtime <= lua_script_last_loaded) { return SLURM_SUCCESS; } /* * Initilize lua */ L = luaL_newstate(); luaL_openlibs(L); if (luaL_loadfile(L, lua_script_path)) { if (L_orig) { (void) error("lua: %s: %s, using previous script", lua_script_path, lua_tostring(L, -1)); lua_close(L); L = L_orig; return SLURM_SUCCESS; } rc = error("lua: %s: %s", lua_script_path, lua_tostring(L, -1)); lua_pop(L, 1); return rc; } /* * Register SLURM functions in lua state: * logging and slurm structure read/write functions */ _register_lua_slurm_output_functions(); _register_lua_slurm_struct_functions(); /* * Run the user script: */ if (lua_pcall(L, 0, 1, 0) != 0) { if (L_orig) { (void) error("job_submit/lua: %s: %s, " "using previous script", lua_script_path, lua_tostring(L, -1)); lua_close(L); L = L_orig; return SLURM_SUCCESS; } rc = error("job_submit/lua: %s: %s", lua_script_path, lua_tostring(L, -1)); lua_pop(L, 1); return rc; } /* * Get any return code from the lua script */ rc = (int) lua_tonumber(L, -1); if (rc != SLURM_SUCCESS) { if (L_orig) { (void) error("job_submit/lua: %s: returned %d " "on load, using previous script", lua_script_path, rc); lua_close(L); L = L_orig; return SLURM_SUCCESS; } (void) error("job_submit/lua: %s: returned %d on load", lua_script_path, rc); lua_pop (L, 1); return rc; } /* * Check for required lua script functions: */ rc = _check_lua_script_functions(); if (rc != SLURM_SUCCESS) { if (L_orig) { (void) error("job_submit/lua: %s: " "required function(s) not present, " "using previous script", lua_script_path); lua_close(L); L = L_orig; return SLURM_SUCCESS; } return rc; } if (L_orig) lua_close(L_orig); lua_script_last_loaded = time(NULL); return SLURM_SUCCESS; }
void evalGenericCommand(redisClient *c, int evalsha) { lua_State *lua = server.lua; char funcname[43]; long long numkeys; int delhook = 0; /* We want the same PRNG sequence at every call so that our PRNG is * not affected by external state. */ redisSrand48(0); /* We set this flag to zero to remember that so far no random command * was called. This way we can allow the user to call commands like * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command * is called (otherwise the replication and AOF would end with non * deterministic sequences). * * Thanks to this flag we'll raise an error every time a write command * is called after a random command was used. */ server.lua_random_dirty = 0; server.lua_write_dirty = 0; /* Get the number of arguments that are keys */ if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK) return; if (numkeys > (c->argc - 3)) { addReplyError(c,"Number of keys can't be greater than number of args"); return; } /* We obtain the script SHA1, then check if this function is already * defined into the Lua state */ funcname[0] = 'f'; funcname[1] = '_'; if (!evalsha) { /* Hash the code if this is an EVAL call */ sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr)); } else { /* We already have the SHA if it is a EVALSHA */ int j; char *sha = c->argv[1]->ptr; for (j = 0; j < 40; j++) funcname[j+2] = tolower(sha[j]); funcname[42] = '\0'; } /* Try to lookup the Lua function */ lua_getglobal(lua, funcname); if (lua_isnil(lua,1)) { lua_pop(lua,1); /* remove the nil from the stack */ /* Function not defined... let's define it if we have the * body of the funciton. If this is an EVALSHA call we can just * return an error. */ if (evalsha) { addReply(c, shared.noscripterr); return; } if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) return; /* Now the following is guaranteed to return non nil */ lua_getglobal(lua, funcname); redisAssert(!lua_isnil(lua,1)); } /* Populate the argv and keys table accordingly to the arguments that * EVAL received. */ luaSetGlobalArray(lua,"KEYS",c->argv+3,numkeys); luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,c->argc-3-numkeys); /* Select the right DB in the context of the Lua client */ selectDb(server.lua_client,c->db->id); /* Set an hook in order to be able to stop the script execution if it * is running for too much time. * We set the hook only if the time limit is enabled as the hook will * make the Lua script execution slower. */ server.lua_caller = c; server.lua_time_start = ustime()/1000; server.lua_kill = 0; if (server.lua_time_limit > 0 && server.masterhost == NULL) { lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000); delhook = 1; } /* At this point whatever this script was never seen before or if it was * already defined, we can call it. We have zero arguments and expect * a single return value. */ if (lua_pcall(lua,0,1,0)) { if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */ if (server.lua_timedout) { server.lua_timedout = 0; /* Restore the readable handler that was unregistered when the * script timeout was detected. */ aeCreateFileEvent(server.el,c->fd,AE_READABLE, readQueryFromClient,c); } server.lua_caller = NULL; selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */ addReplyErrorFormat(c,"Error running script (call to %s): %s\n", funcname, lua_tostring(lua,-1)); lua_pop(lua,1); lua_gc(lua,LUA_GCCOLLECT,0); return; } if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */ server.lua_timedout = 0; server.lua_caller = NULL; selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */ luaReplyToRedisReply(c,lua); lua_gc(lua,LUA_GCSTEP,1); /* If we have slaves attached we want to replicate this command as * EVAL instead of EVALSHA. We do this also in the AOF as currently there * is no easy way to propagate a command in a different way in the AOF * and in the replication link. * * IMPROVEMENT POSSIBLE: * 1) Replicate this command as EVALSHA in the AOF. * 2) Remember what slave already received a given script, and replicate * the EVALSHA against this slaves when possible. */ if (evalsha) { robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr); redisAssertWithInfo(c,NULL,script != NULL); rewriteClientCommandArgument(c,0, resetRefCount(createStringObject("EVAL",4))); rewriteClientCommandArgument(c,1,script); } }
/* Initialize the scripting environment. * It is possible to call this function to reset the scripting environment * assuming that we call scriptingRelease() before. * See scriptingReset() for more information. */ void scriptingInit(void) { lua_State *lua = lua_open(); luaLoadLibraries(lua); luaRemoveUnsupportedFunctions(lua); /* Initialize a dictionary we use to map SHAs to scripts. * This is useful for replication, as we need to replicate EVALSHA * as EVAL, so we need to remember the associated script. */ server.lua_scripts = dictCreate(&dbDictType,NULL); /* Register the redis commands table and fields */ lua_newtable(lua); /* redis.call */ lua_pushstring(lua,"call"); lua_pushcfunction(lua,luaRedisCallCommand); lua_settable(lua,-3); /* redis.pcall */ lua_pushstring(lua,"pcall"); lua_pushcfunction(lua,luaRedisPCallCommand); lua_settable(lua,-3); /* redis.log and log levels. */ lua_pushstring(lua,"log"); lua_pushcfunction(lua,luaLogCommand); lua_settable(lua,-3); lua_pushstring(lua,"LOG_DEBUG"); lua_pushnumber(lua,REDIS_DEBUG); lua_settable(lua,-3); lua_pushstring(lua,"LOG_VERBOSE"); lua_pushnumber(lua,REDIS_VERBOSE); lua_settable(lua,-3); lua_pushstring(lua,"LOG_NOTICE"); lua_pushnumber(lua,REDIS_NOTICE); lua_settable(lua,-3); lua_pushstring(lua,"LOG_WARNING"); lua_pushnumber(lua,REDIS_WARNING); lua_settable(lua,-3); /* redis.sha1hex */ lua_pushstring(lua, "sha1hex"); lua_pushcfunction(lua, luaRedisSha1hexCommand); lua_settable(lua, -3); /* redis.error_reply and redis.status_reply */ lua_pushstring(lua, "error_reply"); lua_pushcfunction(lua, luaRedisErrorReplyCommand); lua_settable(lua, -3); lua_pushstring(lua, "status_reply"); lua_pushcfunction(lua, luaRedisStatusReplyCommand); lua_settable(lua, -3); /* Finally set the table as 'redis' global var. */ lua_setglobal(lua,"redis"); /* Replace math.random and math.randomseed with our implementations. */ lua_getglobal(lua,"math"); lua_pushstring(lua,"random"); lua_pushcfunction(lua,redis_math_random); lua_settable(lua,-3); lua_pushstring(lua,"randomseed"); lua_pushcfunction(lua,redis_math_randomseed); lua_settable(lua,-3); lua_setglobal(lua,"math"); /* Add a helper funciton that we use to sort the multi bulk output of non * deterministic commands, when containing 'false' elements. */ { char *compare_func = "function __redis__compare_helper(a,b)\n" " if a == false then a = '' end\n" " if b == false then b = '' end\n" " return a<b\n" "end\n"; luaL_loadbuffer(lua,compare_func,strlen(compare_func),"@cmp_func_def"); lua_pcall(lua,0,0,0); } /* Create the (non connected) client that we use to execute Redis commands * inside the Lua interpreter. * Note: there is no need to create it again when this function is called * by scriptingReset(). */ if (server.lua_client == NULL) { server.lua_client = createClient(-1); server.lua_client->flags |= REDIS_LUA_CLIENT; } /* Lua beginners ofter don't use "local", this is likely to introduce * subtle bugs in their code. To prevent problems we protect accesses * to global variables. */ scriptingEnableGlobalsProtection(lua); server.lua = lua; }
/* * Arguments: function, [arguments (any) ...] * Returns: [thread_ludata] */ static int thread_run (lua_State *L) { struct sys_thread *vmtd = sys_get_thread(); lua_State *NL; struct sys_thread *td; #ifndef _WIN32 pthread_attr_t attr; int res = 0; #else HANDLE hThr; const int res = 0; #endif if (!vmtd) luaL_argerror(L, 0, "Threading not initialized"); luaL_checktype(L, 1, LUA_TFUNCTION); NL = lua_newthread(L); if (!NL) goto err; td = lua_newuserdata(L, sizeof(struct sys_thread)); memset(td, 0, sizeof(struct sys_thread)); td->mutex = vmtd->mutex; td->L = NL; td->vmtd = vmtd->vmtd; #ifndef _WIN32 if ((res = pthread_attr_init(&attr)) || (res = pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE))) goto err; pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); res = pthread_create(&td->tid, &attr, (thread_func_t) thread_start, td); pthread_attr_destroy(&attr); if (!res) { #else hThr = (HANDLE) _beginthreadex(NULL, THREAD_STACK_SIZE, (thread_func_t) thread_start, td, 0, &td->tid); if (hThr) { CloseHandle(hThr); #endif thread_settable(L, NL, td->tid); /* save thread to avoid GC */ lua_xmove(L, NL, lua_gettop(L)); /* move function and args to NL */ lua_pushlightuserdata(L, td); return 1; } err: return sys_seterror(L, res); } /* * Arguments: function, master (thread_ludata), * [arguments (string | number | boolean | lightuserdata) ...], * thread, thread_udata */ static THREAD_FUNC_API thread_startvm (struct sys_thread *td) { lua_State *L = td->L; thread_settable(L, L, td->tid); sys_set_thread(td); sys_vm2_enter(td); if (lua_pcall(L, lua_gettop(L) - 1, 0, 0)) { if (td->interrupted && lua_touserdata(L, -1) == &g_TLSIndex) lua_pop(L, 1); else lua_error(L); } /* notify event_queue */ if (td->trigger) sys_trigger_notify(&td->trigger, SYS_EVEOF | SYS_EVDEL); lua_close(L); return 0; }
int LuaInterface::pcall(int numArgs, int numRets, int errorFuncIndex) { assert(hasIndex(-numArgs - 1)); return lua_pcall(L, numArgs, numRets, errorFuncIndex); }
int ts_lua_add_module(ts_lua_instance_conf *conf, ts_lua_main_ctx *arr, int n, int argc, char *argv[]) { int i, ret; int t; lua_State *L; for (i = 0; i < n; i++) { L = arr[i].lua; lua_newtable(L); // create this module's global table lua_pushvalue(L, -1); lua_setfield(L, -2, "_G"); lua_newtable(L); lua_rawgeti(L, LUA_REGISTRYINDEX, arr[i].gref); lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); lua_replace(L, LUA_GLOBALSINDEX); if (luaL_loadfile(L, conf->script)) { fprintf(stderr, "[%s] luaL_loadfile %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1)); lua_pop(L, 1); return -1; } if (lua_pcall(L, 0, 0, 0)) { fprintf(stderr, "[%s] lua_pcall %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1)); lua_pop(L, 1); return -1; } /* call "__init__", to parse parameters */ lua_getglobal(L, "__init__"); if (lua_type(L, -1) == LUA_TFUNCTION) { lua_newtable(L); for (t = 0; t < argc; t++) { lua_pushnumber(L, t); lua_pushstring(L, argv[t]); lua_rawset(L, -3); } if (lua_pcall(L, 1, 1, 0)) { fprintf(stderr, "[%s] lua_pcall %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1)); lua_pop(L, 1); return -1; } ret = lua_tonumber(L, -1); lua_pop(L, 1); if (ret) return -1; /* script parse error */ } else { lua_pop(L, 1); /* pop nil */ } lua_pushlightuserdata(L, conf); lua_pushvalue(L, LUA_GLOBALSINDEX); lua_rawset(L, LUA_REGISTRYINDEX); lua_newtable(L); lua_replace(L, LUA_GLOBALSINDEX); // set empty table to global } return 0; }