lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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/