summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/clua.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-21 11:19:35 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-21 11:19:35 +0000
commit6e7c6ae56792add3f8d701eca7d144d96ed19458 (patch)
tree855f8b6bcdd61c92be270aa6df1efbad2f603547 /crawl-ref/source/clua.cc
parentefe55b27c4832476e55ba9100da52daa74fdb75b (diff)
downloadcrawl-ref-6e7c6ae56792add3f8d701eca7d144d96ed19458.tar.gz
crawl-ref-6e7c6ae56792add3f8d701eca7d144d96ed19458.zip
Added support for limiting memory used by the Lua interpreter.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1613 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/clua.cc')
-rw-r--r--crawl-ref/source/clua.cc71
1 files changed, 57 insertions, 14 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index fb36672fe9..d6ddf14a0b 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -11,6 +11,7 @@
#include "chardump.h"
#include "cio.h"
#include "delay.h"
+#include "files.h"
#include "food.h"
#include "invent.h"
#include "initfile.h"
@@ -31,15 +32,7 @@
#include "stuff.h"
#include <cstring>
-
-#ifdef HASH_CONTAINERS
-# include <hash_map>
-# define CHMAP HASH_CONTAINER_NS::hash_map
-#else
-# include <map>
-# define CHMAP std::map
-#endif
-
+#include <map>
#include <cctype>
#define BUGGY_PCALL_ERROR "667: Malformed response to guarded pcall."
@@ -57,23 +50,28 @@
else
static void clua_throttle_hook(lua_State *, lua_Debug *);
+static void *clua_allocator(void *ud, void *ptr, size_t osize, size_t nsize);
static int clua_guarded_pcall(lua_State *);
+static int clua_panic(lua_State *);
CLua clua(true);
const int CLua::MAX_THROTTLE_SLEEPS;
CLua::CLua(bool managed)
- : error(), managed_vm(managed), throttle_unit_lines(10000),
+ : error(), managed_vm(managed), shutting_down(false),
+ throttle_unit_lines(10000),
throttle_sleep_ms(0), throttle_sleep_start(2),
throttle_sleep_end(800), n_throttle_sleeps(0), mixed_call_depth(0),
lua_call_depth(0), max_mixed_call_depth(8),
- max_lua_call_depth(100), _state(NULL), sourced_files(), uniqindex(0L)
+ max_lua_call_depth(100), memory_used(0),
+ _state(NULL), sourced_files(), uniqindex(0L)
{
}
CLua::~CLua()
{
+ shutting_down = true;
if (_state)
lua_close(_state);
}
@@ -546,9 +544,12 @@ void CLua::init_lua()
if (_state)
return;
- _state = lua_open();
+ _state = managed_vm? lua_newstate(clua_allocator, this) : luaL_newstate();
if (!_state)
return;
+
+ lua_atpanic(_state, clua_panic);
+
luaopen_base(_state);
luaopen_string(_state);
luaopen_table(_state);
@@ -2168,7 +2169,7 @@ void lua_open_monsters(lua_State *ls)
#define PATTERN_FLUSH_CEILING 100
-typedef CHMAP<std::string, text_pattern> pattern_map;
+typedef std::map<std::string, text_pattern> pattern_map;
static pattern_map pattern_cache;
static text_pattern &get_text_pattern(const std::string &s, bool checkcase)
@@ -2181,7 +2182,7 @@ static text_pattern &get_text_pattern(const std::string &s, bool checkcase)
pattern_cache.clear();
pattern_cache[s] = text_pattern(s, !checkcase);
- return pattern_cache[s];
+ return (pattern_cache[s]);
}
static int lua_pmatch(lua_State *ls)
@@ -2380,6 +2381,48 @@ bool lua_text_pattern::translate() const
lua_call_throttle::lua_clua_map lua_call_throttle::lua_map;
+// A panic function for the Lua interpreter, usually called when it
+// runs out of memory when trying to load a file or a chunk of Lua from
+// an unprotected Lua op. The only cases of unprotected Lua loads are
+// loads of Lua code from .crawlrc, which is read at start of game.
+//
+// If there's an inordinately large .crawlrc (we're talking seriously
+// massive here) that wants more memory than we're willing to give
+// Lua, then the game will save and exit until the .crawlrc is fixed.
+//
+// Lua can also run out of memory during protected script execution,
+// such as when running a macro or some other game hook, but in such
+// cases the Lua interpreter will throw an exception instead of
+// panicking.
+//
+static int clua_panic(lua_State *ls)
+{
+ if (crawl_state.need_save && !crawl_state.saving_game
+ && !crawl_state.updating_scores)
+ {
+ save_game(true);
+ }
+ return (0);
+}
+
+static void *clua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ CLua *cl = static_cast<CLua *>( ud );
+ cl->memory_used += nsize - osize;
+
+ if (nsize > osize && cl->memory_used >= CLUA_MAX_MEMORY_USE * 1024
+ && cl->mixed_call_depth)
+ return (NULL);
+
+ if (!nsize)
+ {
+ free(ptr);
+ return (NULL);
+ }
+ else
+ return (realloc(ptr, nsize));
+}
+
static void clua_throttle_hook(lua_State *ls, lua_Debug *dbg)
{
CLua *lua = lua_call_throttle::find_clua(ls);