lua-users home
lua-l archive

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



On 11-Oct-06, at 3:20 PM, Glenn Maynard wrote:

On Wed, Oct 11, 2006 at 10:32:45AM -0300, Roberto Ierusalimschy wrote:
lua_sethook has no intention of being "thread safe". As already pointed
out in this discussion, multithreading is a can of worms that opens
the door to hell. It is quite difficult to write correct code with
multithreading, and it is mostly impossible to argue that the code is
correct (although, of course, it can be easy to argue that it is wrong).

However, lua_sethook has a clear intention of being "signal safe". If
it is not, we would like to correct it.

It says "can be called asynchronous".  That sounds like "can be called
from a thread", and that Mike's interpretation, too.  If you only mean
"from a signal", maybe that comment could be clarified.

It also seems like there should be two lua_sethooks; one for signals,
which doesn't lock, and one for threads, which does lua_lock, like other API calls. Otherwise, this is one of the few (that I've seen) functions
which is not threadsafe when locking is enabled.

Remember that every lua_State has its own hook data.

In general, Lua makes no attempt to allow you to simultaneously use the same lua_State in two different OS threads. While Lua itself probably will survive, the same cannot be said of any C function: imagine what would happen if two OS threads both decided to do: lua_pushnumber(L, 1) on the same L. That's clearly a non-starter: if you really need to use the same lua_State in two or more OS threads, you'll need to provide a synchronization mechanism external to the Lua core.

With some limitations, it's reasonably easy to use different related lua_States in different OS threads, and the synchronization mechanism used by Lua (lua_lock and lua_unlock) is intended to make this possible. However, Lua provides no mechanism to synchronize access to shared mutable state; you would have to provide that yourself if it were needed.

Use of the Lua registry is particularly problematic in this regard; luaL_*ref is not threadsafe if used on the registry, and neither is luaL_newmetatable. I haven't looked deeply into the module code, but I'd like to be convinced that the use of the registry to keep the _LOADED table used by the package system is threadsafe, in the sense that it won't fail if two different lua_State's running in two different OS threads both called require(). (It looks to me like it isn't, but maybe I'm missing something.)

However, the lua_State's environment table is certainly available as a kind of thread-local storage, and if that's not enough, there's the possibility of extending the lua_State itself, as mentioned earlier.

Finally, with respect to lua_sethook, there doesn't seem to me to be any point providing a locking version, since that won't help with signal-safety and, as I said earlier, it's the programmers responsibility to ensure that the same lua_State is not being used simultaneously in two OS threads. I suppose there is a question of whether the existing lua_sethook is actually signal safe or not in a multithreaded environment, in the face of the rather underspecified interaction between signals and threads, but I would think the more difficult issue in a signal handler is figuring out which lua_State's sethook should be called.

(In practice, there are some issues with the fact that hooks are state-specific, rather than being part of the global state; for example, it makes it rather more difficult to use hooks to monitor Lua scripts unless you forbid the scripts to use the coroutine library.)