lua-users home
lua-l archive

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


Hi,

For this discussion, assume you have a pointer to a mutex
per lua_State, and that we are using pthreads (to
keep things simple I will cry about Windows later).

The shared lua_State mutex is created on a call to lua_open,
and all child lua_States (created with lua_newthread) point to that same mutex.

This mutex is used to ensure exclusive access to the
lua_State. Accordingly, at a given moment, only one thread
will be running Lua code (or pretty much any Lua API
function, for that matter). Other threads will be blocked
attempting to acquire this mutex, at system calls, or at
other mutexes or condition variables that can be created
and manipulated from Lua code.

Now one of these threads ends up causing lua_close to be
called. Say the main thread decides to quit, for example.

Inside lua_close, the main thread will acquire the lua_State
lock. It will then proceed to destroy everything that was
allocated.

How do we prevent hell from being unleashed?

Child threads currently blocked on cancelation points (such
as those waiting on condition variables, or calling to
read()) can be cancelled one by one from inside lua_close,
as long as we keep a list of created threads.

But what about those blocked on the shared lua_State mutex
itself?  And what about those blocked on some other mutex?

We are not allowed to destroy locked mutexes. We would have
to somehow beg these other threads to unlock whatever they
had locked and politely quit. This can be done by placing
all threads in the assynchronous cancelation state at creation
time, pushing one cancelation handler for each mutex a
thread locks, then looping over all child threads canceling
them and joining them to wait until they terminate naturally.

One might think we would be able to get the __gc metamethod of
each mutex to cancel the thread that has it locked and wait
until that thread terminates, or directly unlock it if that
thread is the same as the one running the __gc metamethod.
But if any thread has more than one mutex locked, we would
it would exit without unlocking the others. We would need
the cancelation handlers anyways...

So, is there really no other way?

BTW, it looks like I can set the __gc metamethod for
threads. If this is really the case, I could use it instead
of keeping a list of threads myself. But still, this looks
like a complicated solution.

Regards,
Diego.