Manlio P. ha scritto:
test
This means that when Nginx detects an error, it can just force a full gc
cycle.
If this still does not sounds safe, Nginx can just create a Lua state
(interpreter) for each request, finalizing it when the request is
finalized.
This is both feasible and efficient (but better is one of Lua language
developer can confirm it).
I have written a small program and I can confirm that opened files are
correctly closed when the Lua interpreter is finalized.
The program is attached: the Lua code simply open a big file and read
all its content in memory.
There is a custom memory allocator that make sure to fail when a large
amount of memory is required.
There is a strange behaviour, however.
The status code returned by luaL_dostring should be
4 (LUA_ERRMEM), instead 1 is returned.
Regards Manlio P.
Manlio P. ha scritto:
test
results (for the same reason), but they may lead to socket/file
descriptor/etc
leak.
I understand the problem, however I think that Lua is still usable.
I’m reading the source code of Lua io library, and any opened file is
closed when reached by the gc.
By the way, I’m reading the source code for the NekoVM file
library,
and it seems that an opened file object must be explicitly closed, it
is not garbage collected.
Moreover, this piece of code (gc_alloc_block function in vm/gc.c) is
quite impressive:
#define ASSERT() (char)NULL = 0
…
p = malloc(sizeof(gc_page));
if( p == NULL )
ASSERT();
Another unhandled memory error is in vm/context.c:
_context *context_new() {
_context *ctx = malloc(sizeof(_context));
pthread_key_create( &ctx->key, NULL );
return ctx;
}
So, unless I’m wrong, NekoVM does seems to meets Igor requirements.
[…]
Regards Manlio P.
Manlio P. ha scritto:
There is a strange behaviour, however.
The status code returned by luaL_dostring should be
4 (LUA_ERRMEM), instead 1 is returned.
Ok, solved.
The last luaL_dostring should be replaced with:
status = luaL_loadstring(L, CHUNCK_2);
if (status != 0) {
printf(“syntax error in CHUNK_2\n”);
return EXIT_FAILURE;
}
status = lua_pcall(L, 0, 0, 0);
msg = lua_tolstring(L, 1, &len);
printf(“execution status 2: %i:%s\n”, status, msg);
since luaL_dostring always returns 1 in case of errors.
Updated code is here: http://rafb.net/p/yOVhjw87.html
Regards Manlio P.
On Sat, 26 Apr 2008 12:46:00 +0200
Manlio P. [email protected] wrote:
The lua_load function reads and parses a Lua code chunk and return
(in the Lua stack) the compiled code (or an error code).
Sure, and you can even byte-compile code into memory buffers by using
luaU_dump (along with a custom writer) and then loading them into the VM
by using lua_load (the luac compiler works by those functions, which
are present in the Lua library, its source code is in luac.c and can be
read easily.)
this.
I am using Lua in a World Dominationâ„¢ project I can’t talk about (and
because it’s fun! :-P)
That method will work, but I think it would be a bit faster not
creating an entire VM on each request. Using lua_newthread you can fork
off a new lua_State from an existing one, which will share the same
globals but will have its own execution stack. You could do:
- Create a lua_State before configuring (call it “main” state)
- Load all Lua code into the “main” state.
- Fork off a new “thread” with lua_newthread using the “main”
lua_State as starting point when a request arrives.
- Run code into the forked “thread”
- Let Lua garbage-collect the finished threads (or force a collection
at the end of the request, or every n-th request, or whatever).
I wrote “thread” with quotes because they are coroutines, not operating
system “full-blown threads”, they are very light and are implemented in
the VM.
One advantage of using coroutines is that they can yield and pass
control asynchronously to Nginx. Coroutines can be resumed from C by
using lua_resume. Also, you can set up a fake global environment on a
coroutine by using lua_setfenv (e.g. to only allow read access to
globals).
Lua is wonderful in many ways, but what I like most is that it gives
you a small set of features which can be used to achieve nearly
everything, hehe.
Just my two cents 
Cheers,
-Adrian
On Sat, Apr 26, 2008 at 05:28:38PM +0200, Manlio P. wrote:
status = luaL_loadstring(L, CHUNCK_2);
since luaL_dostring always returns 1 in case of errors.
Updated code is here: http://rafb.net/p/yOVhjw87.html
Thank you for your investigation. I will look Lua.
Adrian P. ha scritto:
manual and the source code, so better if a Lua developer can confirm
this.
I am using Lua in a World Dominationâ„¢ project I can’t talk about (and
because it’s fun! :-P)
May be it a game? ;-).
That method will work, but I think it would be a bit faster not
creating an entire VM on each request. Using lua_newthread you can fork
off a new lua_State from an existing one, which will share the same
globals but will have its own execution stack.
You could do:
I was suggesting to use one VM per request since you can be sure that
there are no leaks, and you have more control.
As an example in the code I have posted, the file is not closed by just
running a cycle of the gc (but probabily I’m doing it in the wrong way).
Of course this should be a configurable parameter.
Using one VM per request means that one can not have persistent
connections to a database, as an example.
- Create a lua_State before configuring (call it “main” state)
- Load all Lua code into the “main” state.
- Fork off a new “thread” with lua_newthread using the “main”
lua_State as starting point when a request arrives.
How is this possible?
using lua_resume.
Right, this is the main reason why I’m interested in Lua inside Nginx!
Cheers,
-Adrian
Regards Manlio P.
On Sat, 26 Apr 2008 19:42:35 +0200
Manlio P. [email protected] wrote:
Adrian P. ha scritto:
[…]
I am using Lua in a World Dominationâ„¢ project I can’t talk about
(and because it’s fun! :-P)
May be it a game? ;-).
Not precisely… but it is fun to code 
Of course this should be a configurable parameter.
Using one VM per request means that one can not have persistent
connections to a database, as an example.
Well, one can always store persistent values in a hash table in the C
side of the world, and provide a view of it to the Lua side by adding
e.g. an userdata with table metamethds named “persistend” to every VM
state, so one could handle requests the following way:
if persistent.db_conn ~= nil then
db_conn = persistent.db_conn
else
db_conn = persistent.db_conn = open_database_connection()
fi
handle_request(db_conn)
Have a nice day!
-Adrian