lua-users home
lua-l archive

Strange experiences with coroutines while using Copas

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


Hi all,
I'm using Lua 5.0.2, LuaSocket 2.0beta3 w/Compat-5.1r4, and Copas 1.0,
in an environment similar to Xavante.
Am I right in guessing that it's not recommended to use coroutines in
code that is running under copas.addserver()?
Basically, I have a server that reads some stuff from a socket. It then
creates a coroutine for later use. The coroutine reads more stuff from
the socket, and yields it in small chunks. Something like:
 c = coroutine.create(function()
 repeat
 local chunk = skt:receive(chunk_size) -- 'skt' has been
 -- copas.wrap()'ed
 coroutine.yield(chunk)
 length = length - chunk_size
 until length <= 0
 end)
 ...
 repeat
 success, data = coroutine.resume(c)
 if data then process(data) end
 until not success or not data
But this only "sort of" works. The behavior I see is that sporadically
the coroutine.resume(c) gives me a userdata value instead of a string.
I *think* this is because my code, which is running under
copas.addserver(), is already a coroutine in the eyes of Copas... and
the skt:receive is already doing a coroutine.yield(), and this is
interfering with my use of it. So there's a race condition of sorts,
and sometimes my code receives the string that I am yielding, but
sometimes it receives the socket object that Copas is yielding.
Is that close to right?
There's more, though - and it's even stranger :)
I decided that I would rewrite my code as an iterator to try to work
around this problem. Something like:
 c = function()
 local length = length
 return function()
 if length > 0 then
 local chunk = skt:receive(chunk_size)
 length = length - chunk_size
 return chunk
 end
 end
 end)
 ...
 for data in c() do
 process(data)
 end
Trying this, I get the following somewhat mystifying error message:
 attempt to yield across metamethod/C-call boundary
But if I rewrite the last part as
 local iter = c()
 data = iter()
 while data do
 process(data)
 data = iter()
 end
...it works again, but only "sort of" - it seems to still have some kind
of race condition with something inside Copas, since it doesn't receive
all the chunks that should be sent, and it sometimes gets data chunks of
unexpected sizes, with no consistent pattern that I can discern.
Thanks in advance for any insight into these oddities.
-Chris

AltStyle によって変換されたページ (->オリジナル) /