lua_pcall with our traceback handler and memory and instruction step * limiting. * On error, traceback will be on top of stack */
| 2106 | * limiting. |
| 2107 | * On error, traceback will be on top of stack */ |
| 2108 | int |
| 2109 | nhl_pcall(lua_State *L, int nargs, int nresults, const char *name) |
| 2110 | { |
| 2111 | struct nhl_user_data *nud; |
| 2112 | int rv; |
| 2113 | |
| 2114 | lua_pushcfunction(L, traceback_handler); |
| 2115 | lua_insert(L, 1); |
| 2116 | (void) lua_getallocf(L, (void **) &nud); |
| 2117 | #ifdef NHL_SANDBOX |
| 2118 | if (nud && name) { |
| 2119 | nud->name = name; |
| 2120 | } |
| 2121 | /* NB: We don't need to deal with nud->memlimit - Lua handles that. */ |
| 2122 | if (nud && (nud->steps || nud->perpcall)) { |
| 2123 | if (nud->perpcall) { |
| 2124 | nud->steps = nud->perpcall; |
| 2125 | nud->statctr = 0; |
| 2126 | } |
| 2127 | if (setjmp(nud->jb)) { |
| 2128 | /* panic, because we don't know if the game state is corrupt */ |
| 2129 | /* XXX can we get a lua stack trace as well? */ |
| 2130 | panic("Lua time exceeded %d:%s", nud->sid, |
| 2131 | nud->name ? nud->name : "(unknown)"); |
| 2132 | } |
| 2133 | } |
| 2134 | #endif |
| 2135 | |
| 2136 | rv = lua_pcall(L, nargs, nresults, 1); |
| 2137 | |
| 2138 | lua_remove(L, 1); /* remove handler */ |
| 2139 | |
| 2140 | #ifdef NHL_SANDBOX |
| 2141 | if (nud && nud->perpcall && gl.loglua) { |
| 2142 | long ic = nud->statctr * NHL_SB_STEPSIZE; // an approximation |
| 2143 | livelog_printf(LL_DEBUG, "LUASTATS PCAL %d:%s %ld", nud->sid, |
| 2144 | nud->name, ic); |
| 2145 | } |
| 2146 | if (nud && nud->memlimit && gl.loglua) { |
| 2147 | livelog_printf(LL_DEBUG, "LUASTATS PMEM %d:%s %lu", nud->sid, |
| 2148 | nud->name, (long unsigned) nhl_getmeminuse(L)); |
| 2149 | } |
| 2150 | #endif |
| 2151 | return rv; |
| 2152 | } |
| 2153 | |
| 2154 | int |
| 2155 | nhl_pcall_handle(lua_State *L, int nargs, int nresults, const char *name, |
no test coverage detected