Attempt to yield across C-call boundary

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
zet
Prole
Posts: 3
Joined: Fri Jun 02, 2017 7:18 am

Attempt to yield across C-call boundary

Post by zet »

I'm trying to make a presentation about Lua in Lua and I picked Löve for doing this.
The idea is simple (and I have done that in the past):
1) Loadstring(code)
2) create coroutine
3) set debug hook on *that* coroutine
4) step through the code by yielding in the hook method

The requirement for doing this is having coco or LuaJIT (which has coco built in).
Löve comes with LuaJIT, so I didn't expect this not to work, but it doesn't - for several reasons.

Firstly, I looks like to me that Löve tries to make debugging easier and simply hooks the debug.sethook function into every coroutine so the debugging code will get called just everywhere (in native Lua you have to deal with it - and while it's complicated, you can deal with this).
While this is certainly convenient, it's a bit nasty if you specifically just want to set the hook on one particular coroutine. If you want to use coroutines for simulating agents, you currently can't just debug one single agent - the entire engine will be subject of debugging.

The next thing is the yielding: I am puzzled why this doesn't work. LuaJIT can do this. I assume coroutine.create passes a -1 to the wrapped LuaJIT method to signal it shouldn't use a C-Stack?

Are there ways how to deal with that? The Löve.Thread API doesn't look I want to use it for this, it would make things a good deal more complex.
zet
Prole
Posts: 3
Joined: Fri Jun 02, 2017 7:18 am

Re: Attempt to yield across C-call boundary

Post by zet »

I started looking into the source code of Löve, but seemingly I can't find any modifications. I compared it with another engine which uses LuaJIT 1.1.5

Here's the code in question:

Code: Select all

function foo()
	for i=1,10 do
		print(i)
	end
end

co = coroutine.create(foo)
jit.off(true,true)
debug.sethook(co,function(...)print(">>",...)coroutine.yield()end,"l")

for i=1,5 do
	coroutine.resume(co)
end

--[[
expected output:
>>      line    2
>>      line    3
1
>>      line    2
>>      line    3
2
>>      line    2
]]

--[[
Löve engine output:
>>        line    11
Error: main.lua:9: attempt to yield across C-call boundary
stack traceback:
        [C]: in function 'yield'
        main.lua:9: in function <main.lua:9>
        main.lua:11: in main chunk
        [C]: in function 'require'
        [string "boot.lua"]:429: in function <[string "boot.lua"]:275>
        [C]: in function 'xpcall'
>>      line    568
>>      line    2
]]
I'm still searching for an explanation why this isn't working in Löve for me ...
By the way, Löve crashes also after executing this upon exit.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Attempt to yield across C-call boundary

Post by raidho36 »

http://luajit.org/status.html
  • The Lua debug API is missing a couple of features (return hooks for non-Lua functions) and shows slightly different behavior in LuaJIT (no per-coroutine hooks, no tail call counting).
Nothing LÖVE can do about it. You can however try building LÖVE with a LuaJIT version that doesn't have such problem, or with vanilla Lua. Alternatively, you can try using real threads. They are implemented as totally separate Lua states so there shouldn't be such problems, and these threads do actually run in their own CPU threads.
zet
Prole
Posts: 3
Joined: Fri Jun 02, 2017 7:18 am

Re: Attempt to yield across C-call boundary

Post by zet »

Ah, thank you for clearing that up. I didn't know that LuaJIT 2 changed debug hooks to a global thing. That is ... unfortunate. I still don't get it though why I can't yield from the debug hook function. This used to work ...
I will continue to research this. I would prefer not having to compile Löve myself - even though it would be useful to be able to do that, I'm reluctant to set up the environment for it.
Rusketh
Prole
Posts: 2
Joined: Mon Jun 12, 2017 7:03 pm

Re: Attempt to yield across C-call boundary

Post by Rusketh »

Yep, lua simply does not support yeild from inside a debughook. I tried to do this with a few projects in gmod and eventualy a bunch of us found out that native lua just can not do it. I think its because the debughook is not called with in the same luastack as the co-routine but instead is called by C.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 5 guests