COMMENCE EPIC QUADPOST!
#1
the resume-line in init.lua is what keeps computers running.
that resume executes the systems' coroutines until they yield again (or quit).
each computer has it's own coroutine.
#2
the server-log you posted looks like the systems crash while booting and try to restart then. which except for the crashing part would be correct. it should look more like this:
Code: Select all
16:56:04: ACTION[ServerThread]: dronetest: on_receive_fields received ''
16:56:04: ACTION[ServerThread]: dronetest: STATUS: suspended
16:56:04: ACTION[ServerThread]: dronetest: TYPE: table
16:56:04: ACTION[ServerThread]: dronetest: System #1 has been activated, now 1 systems active.
16:56:04: ACTION[ServerThread]: dronetest: system 1 generated output: System #1 has been activated.
16:56:04: ACTION[ServerThread]: dronetest: system 1 generated output: System #1 is booting!
16:56:04: ACTION[ServerThread]: dronetest: system 1 generated output: Finished booting #1, dropping to shell.
SEND
this probably caused by an error in your bootstrap (as it did not get to the "is booting" message).
however, in such cases errors should be thrown - but i too had some cases which would just fail silently in lua.
take out api you last added to bootstrap to check if error lies there. also try if it's same error if you just use one computer in a clean world (if that works there are ID-problems somewhere)
#3
i think you're misunderstanding the way the environments work now - bootstrap does not have access to anything it shouldn't. also the approach is whitelisting, in dronetest/init.lua userspace_environment gets prepared, which is a clean environment to which safe functions are supposed to be added. there are some unsafe ones in there i added for debugging.
bootstrap runs in that userspace-environment.
it is sys.loadApi that brings in stuff from the unsafe global environment, and it can only be used to load apis - which in turn must be save to be accessed from userspace.
so bootstrap is actually very much sandboxed - like all other userspace code it just has the ability to loadApi other stuff.
i added a few lines to bootstrap to print out its current environment, and it looks like this:
Code: Select all
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: System #1 is booting!
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: pairs (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: table (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: mod_dir (string)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: fs (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: sys (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: peripheral (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: processInput (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: dump (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: ipairs (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: mod_name (string)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: term (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: print (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: math (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: getId (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: os (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: _G (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: pcall (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: string (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: type (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: count (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: shell (table)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: bootstrap env: xpcall (function)
17:08:17: ACTION[ServerThread]: dronetest: system 1 generated output: Finished booting #1, dropping to shell.
as you can see, this is the whitelisted sandbox environment specified earlier.
if you introduce bugs in apis there will be crashes - its as simple as that - does not matter when you add the apis to userspace.
the fact that there are functions whitelisted to userspace that should not be there (like getfenv) is only for trying out stuff more easily. they can just be removed from dronetest/init.lua userspace_environment definition to have them be gone.
i think that link to the lua-wiki is even in the code somewhere, or at least was.
maybe the name bootstrap is confusing, i also removed the =nil s from bootstrap to make it more obvious this is userspace.
it could also be called init or bios or loader or this-is-the-function-that-runs-first-in-userspace.
it really, really does not have global access.
i don't even really get where you got the idea it might have.
the only way to expose globalspace to userspace are apis and the sys-object.
this can only be breached by using a bad function from an api, that somehow returns its own globalspace.
the system-apis must be accessible to userspace, obviously, but they *must* have access to globalspace to have any use - otherwise it would not be possible to actually interact with the gameworld from userspace in any way.
(you could basically just run 1+1 and not even see the output).
if they do not need access to the minetest.* object and all the other stuff,
they are not system-apis but userspace-apis,
and shall be included from userspace to userspace using your os.loadlib for example.
that is a *very* important distinction.
nothing stops us from having as many userspace-only-apis as we want, but the basic system-apis that need to have access to the global env are simply a must, not by preference, but by cold logic - these simply must be callable from userspace but have access to globalspace.
however, if you don't believe me (which you should seeing the output of that print), branch the project and try a different way.
branch for large changes to test them out without confusing the rest of the team, well, me ;)
also that way we can compare branches to see how functionality actually differs.
in this case we would probably see that there aren't many ways to sandbox a coroutine, and doing it differently would most likely end up doing it the same way but just calling functions differently.
it basically always is this:
local f = function() print("hello from userspace") end
setfenv(f,{print=print}) -- nothing can be done in that env but print stuff
local co = coroutine.create(f)
coroutine.resume(co)
and this is what we do right now too.
excuse that wall-of-text, but i do think this is an important matter.
#4
by the way - to get access to the current userspace from an api's globalspace, you can do getfenv(2) if the apifunction was called from userspace (like in shell.run i think) to get the safe environment. thats usefull to have an api load functions and have them run in userspace, instead of an empty environment for example.
also shadowninja has pushed the fix for issue #1709, and if it works, a lot of stuff can move on.