some minetest.* luafuncs don't work when called by coroutine

User avatar
ninnghazad
Member
 
Posts: 36
Joined: Fri Sep 26, 2014 12:33
GitHub: ninnghazad
IRC: ninnghazad
In-game: ninnghazad

some minetest.* luafuncs don't work when called by coroutine

by ninnghazad » Tue Sep 30, 2014 13:58

Trying to call minetest.get_objects_inside_radius from a coroutine will segfault and crash the game:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_globalstep(function(dtime)
   local p = minetest.get_player_by_name("singleplayer")
   if not p then return end
   local pos = p:getpos()
   
   print("TEST0") -- works
   print(dump(minetest.get_objects_inside_radius(pos,3)))

   print("TEST1") -- works
   pcall(function() print(dump(minetest.get_objects_inside_radius(pos,3))) end)
   
   print("TEST2") -- segfaults!
   local co = coroutine.create(function() print(dump(minetest.get_objects_inside_radius(pos,3))) end)
   while coroutine.status(co) == "suspended" do coroutine.resume(co) end
   
   print("TEST3")
   local co = coroutine.create(function() pcall(function() print(dump(minetest.get_objects_inside_radius(pos,3))) end) end)
   while coroutine.status(co) == "suspended" do coroutine.resume(co) end
   
   return true
end)


Is this expected behaviour or a bug?

Segfault happens in lua_rawseti(L, -2, ++i); in l_env.cpp:463
this is latest git with minetest_game on debian 64.
quick bt without symbols:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#0  0x00007ffff6132e51 in lua_rawseti () from /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2
#1  0x000000000058da39 in ModApiEnvMod::l_get_objects_inside_radius(lua_State*) ()
#2  0x0000000000574646 in script_exception_wrapper(lua_State*, int (*)(lua_State*)) ()
#3  0x00007ffff60f0ade in ?? () from /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2
#4  0x00007ffff60f15a5 in ?? () from /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2
#5  0x00007ffff6133f60 in lua_pcall () from /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2
#6  0x0000000000574842 in script_run_callbacks(lua_State*, int, RunCallbacksMode) ()
#7  0x000000000057ae3a in ScriptApiEnv::environment_Step(float) ()
#8  0x0000000000699fc4 in ServerEnvironment::step(float) ()
#9  0x00000000007ddda3 in Server::AsyncRunStep(bool) ()
#10 0x00000000007ea3b3 in ServerThread::Thread() ()
#11 0x0000000000565353 in JThread::TheThread(void*) ()
#12 0x00007ffff5cca0a4 in start_thread (arg=0x7fffec9b7700) at pthread_create.c:309
#13 0x00007ffff4b67c2d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111


EDIT: just noticed this goes for other functions too.
minetest.get_player_by_name("singleplayer"):get_player_name()
for example will not return "singleplayer" when called from a coroutine.

EDIT:
made a simple example and renamed thread:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_globalstep(function(dtime)
   local p = minetest.get_player_by_name("singleplayer")
   if not p then return end
   
   print("TEST 0: "..p:get_player_name().." "..type(p))
   
   local function e(msg) print("TESTERROR: "..msg) end
   local function f()
      print("TEST 1: "..p:get_player_name().." "..type(p))
      
      p = minetest.get_player_by_name("singleplayer")
                if type(p) == string then
              print("TEST 2: "..p.." "..type(p))
                else
                        print("TEST 2: "..p:get_player_name().." "..type(p))
      end
   end
   
   local co = coroutine.create(function() xpcall(f,e) end)
   while coroutine.status(co) == "suspended" do coroutine.resume(co) end
   
   error("bail")
   
   return true
end)


expected output:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
TEST 0: singleplayer userdata
TEST 1: singleplayer userdata
TEST 2: singleplayer userdata



actual output:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
TEST 0: singleplayer userdata
TEST 1: singleplayer userdata
TEST 2: singleplayer string
 

User avatar
ninnghazad
Member
 
Posts: 36
Joined: Fri Sep 26, 2014 12:33
GitHub: ninnghazad
IRC: ninnghazad
In-game: ninnghazad

Re: some minetest.* luafuncs don't work when called by corou

by ninnghazad » Wed Oct 01, 2014 17:55

i investigated further and found that in
lua_api/l_env.cpp
within
int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
the lua_State *L differs when called from coroutine in comparison to a direct call to get_objects_inside_radius.
when called from coroutine the entries in L are shifted one place.
L[-2] contains, when the function is called from a coroutine, the specified radius - which is in L[-3] otherwise.

that somewhat explains why minetest.get_player_by_name returns the name and not the player in that case.

no idea yet what this means or how to fix it.
 

User avatar
ninnghazad
Member
 
Posts: 36
Joined: Fri Sep 26, 2014 12:33
GitHub: ninnghazad
IRC: ninnghazad
In-game: ninnghazad

Re: some minetest.* luafuncs don't work when called by corou

by ninnghazad » Thu Oct 02, 2014 11:14

 


Return to Minetest Problems

Who is online

Users browsing this forum: Bing [Bot] and 9 guests

cron