lua-users home
lua-l archive

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


I have some threads that run in a basic sandbox. In C I create an
environment table and a metatable, set the __index field of the
metatable to the global environment and then set the environment table
for the thread. My intent is to create threads that run in their own
evironment but have full access to the current global environment. 

However I have problems when using require in these threads. Consider:

threadFile.lua:
require "someModule"

local function doIt()
	someModule:doSomething()
end

someModule.lua:
module(...,package.seeall)
function _M:doSomething()
	print "doSomething"
end

The first time I run threadFile.lua in my sandboxed thread, everything
works normally. However, after creating a second thread and running
threadFile.lua I get the error "attempt to index global 'someModule' (a
nil value)".

Now what I think is happening is that the first time require is called,
it looks up the package table, which it gets from the main global
environment via the sandbox metatable. It then sets
package.loaded["someModule"] in the global environment which means that
it persists past the lifetime of the actual thread. So the second time I
try to run the file, require sees that package.loaded["someModule"] is
already true so it doesn't load the file again. But the actual closure
for someModule has been collected since it existed inside the first
thread's environment.

What is the simplest way to avoid this problem?

I can fix it by calling package.loaded["someModule"] just before the
thread terminates, but that seems tedious and error prone. It would be
very easy to miss some files. Is there a way to make this work
correctly?

I think creating new tables for package and package.loaded inside the
thread environment, with the new package.loaded having a metatable set
to the main thread's package.loaded table (to avoid reloading modules
that are already visible via the global environment). Would this
approach work? Are there any other tables used by require that I would
also need to treat this way?

- DC