lua協程一則報錯解決“attempt to yield across metamethod/C-call boundary”


問題

attempt to yield across metamethod/C-call boundary

 

需求跟如下帖子中描述一致:

http://bbs.chinaunix.net/forum.php?mod=viewthread&action=printable&tid=4065715

模擬一個場景,在C中創建出coroutine來執行Lua腳本,並且提供C API給Lua使用,當某些操作可能會阻塞時(如網絡I/O),C函數中執行yield將協程切換出去,然后未來的某個時刻,如果條件滿足則resume 繼續執行后面的腳本.我寫了個demo程序是這樣的:

 

但是使用此帖子中的 方法的, 將resume和yield都放在c中實現, 也沒有解決問題。

使用lua版本為 5.1.4

解法

http://stackoverflow.com/questions/8459459/lua-coroutine-error-tempt-to-yield-across-metamethod-c-call-boundary

There are several things you can do if you cannot change your code to avoid the C/metamethod boundary:

  • If you are using standard Lua, and are compiling it yourself, try patching it with Coco — True C Coroutines for Lua.

    True C coroutine semantics mean you can yield from a coroutine across a C call boundary and resume back to it.

  • Try using LuaJIT instead of the standard Lua interpreter. It uses a fully resumable VM meaning the boundary is not an issue.

  • Try using Lua 5.2. It features yieldable pcall and metamethods which means that it can handle your problem. However, there are some changes and incompatibilities between Lua 5.1 and Lua 5.2.

不改代碼的話,有三種解法。

第一種,  打個補丁,最簡單,對現有代碼影響最小。

故使用這個方法。

 

coco patch

http://coco.luajit.org/

Coco is a small extension to get True C Coroutine semantics for Lua 5.1. Coco is available as a patch set against the standard Lua 5.1.5 source distribution.

Coco is also integrated into LuaJIT 1.x to allow yielding for JIT compiled functions. But note that Coco does not depend on LuaJIT and works fine with plain Lua.

Coco is Copyright © 2004-2016 Mike Pall. Coco is free software, released under the MIT license (same license as the Lua core).

 

由於其是基於5.1.5開發, 將patch移植到5.1.4版本還有一些比對工作。 如何將patch還原為old new, 可以使用前面博文介紹。

 

將patch移到版本中后發現,還是不生效。

最后確定是, c中開辟線程空間的時候, 沒有使用 coco的接口, 還是使用 lua的原生接口。

 

http://lua-users.org/lists/lua-l/2011-10/msg00461.html

 

On 10/15/2011 5:35 PM, Szymon Gatner wrote:
>   lua_State* coro = lua_newthread(L);

You need to use lua_newcthread(). Otherwise LuaJIT 1.x doesn't create a
C stack.

 

http://coco.luajit.org/api.html

lua_State *lua_newcthread(lua_State *L, int cstacksize)

This is an (optional) new function that allows you to create a coroutine with an associated C stack directly from the C API. Other than that it works the same as lua_newthread(L).

You have to declare this function as extern yourself, since it's not part of the official Lua API. This means that a C module that uses this call cannot be loaded with standard Lua. This may be intentional.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM