# HG changeset patch # User daurnimator # Date 1421192160 18000 # Node ID e4d443d05626cb672e5a5f2c73d40e638d1a4372 # Parent 605a87e90e274c75c963069cbedf26f2887d19f0 net.cqueues: Fixes hardcoded timeout for first iteration This was originally put in place as a fix for what ended up a cqueues bug: https://github.com/wahern/cqueues/issues/40 A check for a cqueues version with the bug fix is included. diff -r 605a87e90e27 -r e4d443d05626 net/cqueues.lua --- a/net/cqueues.lua Tue Jan 06 20:01:59 2015 -0500 +++ b/net/cqueues.lua Tue Jan 13 18:36:00 2015 -0500 @@ -9,6 +9,7 @@ local server = require "net.server"; local cqueues = require "cqueues"; +assert(cqueues.VERSION >= 20150112, "cqueues newer than 20151013 required") -- Create a single top level cqueue local cq; @@ -43,23 +44,27 @@ cq = cqueues.new(); -- Only need to listen for readable; cqueues handles everything under the hood local EV_READ = server.event.EV_READ; + -- Convert a cqueues timeout to an acceptable timeout for luaevent + local function luaevent_safe_timeout(cq) + local t = cq:timeout(); + -- if you give luaevent 0 or nil, it re-uses the previous timeout. + if t == 0 then + t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`) + elseif t == nil then -- pick something big if we don't have one + t = 0x7FFFFFFF; -- largest 32bit int + end + return t + end local event_handle; event_handle = server.base:addevent(cq:pollfd(), EV_READ, function(e) -- Need to reference event_handle or this callback will get collected -- This creates a circular reference that can only be broken if event_handle is manually :close()'d local _ = event_handle; + -- Run as many cqueues things as possible (with a timeout of 0) + -- If an error is thrown, it will break the libevent loop; but prosody resumes after logging a top level error assert(cq:loop(0)); - -- Convert a cq timeout to an acceptable timeout for luaevent - local t = cq:timeout(); - if t == 0 then -- if you give luaevent 0, it won't call this callback again - t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`) - elseif t == nil then -- you always need to give a timeout, pick something big if we don't have one - t = 0x7FFFFFFF; -- largest 32bit int - end - return EV_READ, t; - end, - -- Schedule the callback to fire on first tick to ensure any cq:wrap calls that happen during start-up are serviced. - 0.000001); + return EV_READ, luaevent_safe_timeout(cq); + end, luaevent_safe_timeout(cq)); else error "NYI" end