Software /
code /
prosody
File
util/timer.lua @ 10851:6cf16abd0976
net.server_select: Ensure onconnect is always called before onincoming
This changes the code to call onconnect when the first data is sucessfully
read or written, instead of simply when the socket first becomes writable.
A writable socket can mean a connection error, and if the client already
sent some data it may get passed to onincoming before processing writable
sockets. This fixes the issue.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 01 Jun 2020 13:38:47 +0100 |
parent | 9562:acf74ad0b795 |
child | 10981:e6c1e92cc7a7 |
child | 11263:1274deeab39a |
line wrap: on
line source
-- Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- local indexedbheap = require "util.indexedbheap"; local log = require "util.logger".init("timer"); local server = require "net.server"; local get_time = require "util.time".now local type = type; local debug_traceback = debug.traceback; local tostring = tostring; local xpcall = require "util.xpcall".xpcall; local math_max = math.max; local _ENV = nil; -- luacheck: std none local _add_task = server.add_task; local _server_timer; local _active_timers = 0; local h = indexedbheap.create(); local params = {}; local next_time = nil; local function _traceback_handler(err) log("error", "Traceback[timer]: %s", debug_traceback(tostring(err), 2)); end local function _on_timer(now) local peek; while true do peek = h:peek(); if peek == nil or peek > now then break; end local _, callback, id = h:pop(); local param = params[id]; params[id] = nil; --item(now, id, _param); local success, err = xpcall(callback, _traceback_handler, now, id, param); if success and type(err) == "number" then h:insert(callback, err + now, id); -- re-add params[id] = param; end end if peek ~= nil and _active_timers > 1 and peek == next_time then -- Another instance of _on_timer already set next_time to the same value, -- so it should be safe to not renew this timer event peek = nil; else next_time = peek; end if peek then -- peek is the time of the next event return peek - now; end _active_timers = _active_timers - 1; end local function add_task(delay, callback, param) local current_time = get_time(); local event_time = current_time + delay; local id = h:insert(callback, event_time); params[id] = param; if next_time == nil or event_time < next_time then next_time = event_time; if _server_timer then _server_timer:close(); _server_timer = nil; else _active_timers = _active_timers + 1; end _server_timer = _add_task(next_time - current_time, _on_timer); end return id; end local function stop(id) params[id] = nil; local result, item, result_sync = h:remove(id); local peek = h:peek(); if peek ~= next_time and _server_timer then next_time = peek; _server_timer:close(); if next_time ~= nil then _server_timer = _add_task(math_max(next_time - get_time(), 0), _on_timer); end end return result, item, result_sync; end local function reschedule(id, delay) local current_time = get_time(); local event_time = current_time + delay; h:reprioritize(id, delay); if next_time == nil or event_time < next_time then next_time = event_time; _add_task(next_time - current_time, _on_timer); end return id; end return { add_task = add_task; stop = stop; reschedule = reschedule; };