[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Persistent Lua state
- From: Andre de Leiradella <leiradella@...>
- Date: Fri, 11 Jul 2003 12:34:52 -0300
Hi All,
>From time to time messages asking for how to make a Lua state persist
between runs of a program appear in the list. I had myself the need to such
a thing, and in my case saving Lua tables as strings wouldn't do the job.
Playing around with lua-5.0 and mmalloc (the memory-mapped malloc routines
that come with gdb), I succeeded to make the Lua state persistent. My tests
were composed of two programs, one that creates a Lua state and one that
executes arbitrary Lua code in the saved state:
create.c ----------------------------------------
#include <mmalloc.h>
#include <lua.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void *md;
void *myrealloc(void *ptr, size_t size) {
return mrealloc(md, ptr, size);
}
void myfree(void *ptr) {
mfree(md, ptr);
}
int main() {
int fd;
lua_State *L;
fd = open("memory", O_CREAT | O_RDWR);
md = mmalloc_attach(fd, NULL);
L = lua_open();
mmalloc_setkey(md, 0, L);
mmalloc_detach(md);
close(fd);
return 0;
}
----------------------------------------
exec.c ---------------------------------
#include <mmalloc.h>
#include <lua.h>
#include <lauxlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void *md;
void *myrealloc(void *ptr, size_t size) {
return mrealloc(md, ptr, size);
}
void myfree(void *ptr) {
mfree(md, ptr);
}
static int print(lua_State *L) {
printf("%s\n", lua_tostring(L, -1));
return 0;
}
int main(int argc, char *argv[]) {
int fd;
lua_State *L;
fd = open("memory", O_RDWR);
md = mmalloc_attach(fd, NULL);
L = mmalloc_getkey(md, 0);
lua_register(L, "print", print);
if (argc == 2)
lua_dostring(L, argv[1]);
mmalloc_detach(md);
close(fd);
return 0;
}
-------------------------------------
Lua was compiled with -Dl_realloc=myrealloc and -Dl_free=myfree. Everything
runs on a RedHat 9.0. After the execution of create, a file called "memory"
is created. Then one can run exec multiple times to run arbitrary Lua code:
# ./create
# ls -l
total 308
-rwxr-xr-x 1 root root 114789 Jul 11 11:35 create
-rw-r--r-- 1 root root 443 Jul 11 11:35 create.c
-rw-r--r-- 1 root root 1260 Jul 11 11:35 create.o
-rwxr-xr-x 1 root root 122409 Jul 11 11:51 exec
-rw-r--r-- 1 root root 623 Jul 11 11:51 exec.c
-rw-r--r-- 1 root root 1576 Jul 11 11:51 exec.o
-rw-r--r-- 1 root root 327 Jul 11 11:34 Makefile
--wsr-s--- 1 root root 40960 Jul 11 12:21 memory
# ./exec "a=1"
# ./exec "print(a)"
1
# ./exec "a={name='andre'}"
# ./exec "print(a.name)"
andre
# ./exec "function fat(x) if x < 2 then return 1 end return fat(x - 1) * x
end"
# ./exec "print(fat(5))"
120
# ./exec "print('10! = ' .. fat(10)) print(a.name)"
10! = 3628800
andre
# ls -l
total 320
-rwxr-xr-x 1 root root 114789 Jul 11 11:35 create
-rw-r--r-- 1 root root 443 Jul 11 11:35 create.c
-rw-r--r-- 1 root root 1260 Jul 11 11:35 create.o
-rwxr-xr-x 1 root root 122409 Jul 11 11:51 exec
-rw-r--r-- 1 root root 623 Jul 11 11:51 exec.c
-rw-r--r-- 1 root root 1576 Jul 11 11:51 exec.o
-rw-r--r-- 1 root root 327 Jul 11 11:34 Makefile
--wsr-s--- 1 root root 49152 Jul 11 12:23 memory
#
The only problem I found so far is related to C functions registered in the
state. As their address may change between runs, all C functions must be
re-registered in exec.c. Besides that everything is running just fine. The
next step: add threads and socket support.
For those who find mmalloc's license (GPL) too restrictive, it's not hard to
find free memory allocation routines on the Internet. This plus changing
calls to sbrk to some function that increments the size of the memory-mapped
file if there's not enough space and some functions to initialize and
shutdown the system will set you free from mmalloc.
And finally a question to Lua authors: do you think this approach can cause
problems in Lua internals?
Having asked that, enjoy!
Andre de Leiradella
http://www.geocities.com/andre_leiradella/