X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fhttpd%2Fluasrc%2Fhttpd.lua;h=f471e6b0cc63bf6501d93b0d98f657eaa7fbce1d;hp=a9b1ccbb4cb18bd1771c77e7a99dea2027b6abdc;hb=7d0b17c7d3b344a1cdb1e12e281057036e433a2e;hpb=7a4aa85dd64f72b9edcbf9310d0d95e59960d84e diff --git a/libs/httpd/luasrc/httpd.lua b/libs/httpd/luasrc/httpd.lua index a9b1ccbb4..f471e6b0c 100644 --- a/libs/httpd/luasrc/httpd.lua +++ b/libs/httpd/luasrc/httpd.lua @@ -36,8 +36,8 @@ function Thread.__init__(self, socket, func) self.waiting = false end -function Thread.getidletime(self) - return os.difftime(os.time(), self.stamp) +function Thread.touched(self) + return self.stamp end function Thread.iswaiting(self) @@ -61,8 +61,8 @@ function Thread.resume(self, ...) return coroutine.resume(self.routine, self, ...) end -function Thread.status(self) - return coroutine.status(self.routine) +function Thread.isdead(self) + return coroutine.status(self.routine) == "dead" end function Thread.touch(self) @@ -71,7 +71,7 @@ end Daemon = luci.util.class() -function Daemon.__init__(self, threadlimit, timeout) +function Daemon.__init__(self, threadlimit, waittime, timeout) self.reading = {} self.threads = {} self.handler = {} @@ -82,7 +82,29 @@ function Daemon.__init__(self, threadlimit, timeout) self.debug = false self.threadlimit = threadlimit - self.timeout = timeout or 0.1 + self.waittime = waittime or 0.1 + self.timeout = timeout or 90 +end + +function Daemon.remove_dead(self, thread) + if self.debug then + self:dprint("Completed " .. tostring(thread)) + end + thread.socket:close() + self.threadc = self.threadc - 1 + self.threads[thread.socket] = nil +end + +function Daemon.kill_timedout(self) + local now = os.time() + + for sock, thread in pairs(self.threads) do + if os.difftime(now, thread:touched()) > self.timeout then + self.threads[sock] = nil + self.threadc = self.threadc - 1 + sock:close() + end + end end function Daemon.dprint(self, msg) @@ -129,6 +151,8 @@ function Daemon.step(self) -- reject client else + self:kill_timedout() + if self.debug then self:dprint("Rejected incoming connection from " .. sock:getpeername()) end @@ -143,30 +167,23 @@ function Daemon.step(self) end -- create client handler - for sock, thread in pairs( self.threads ) do - - -- reap dead clients - if thread:status() == "dead" then - if self.debug then - self:dprint("Completed " .. tostring(thread)) - end - sock:close() - self.threadc = self.threadc - 1 - self.threads[sock] = nil + for sock, thread in pairs( self.threads ) do -- resume working threads - elseif not thread:iswaiting() then + if not thread:iswaiting() then if self.debug then self:dprint("Resuming " .. tostring(thread)) end local stat, err = thread:resume() - if stat then + if stat and not thread:isdead() then thread:touch() if not thread:iswaiting() then working = true else table.insert(self.waiting, sock) end + else + self:remove_dead(thread) end if self.debug then @@ -181,24 +198,30 @@ function Daemon.step(self) -- check for data on waiting threads input, output, err = socket.select( self.waiting, nil, 0 ) - for i, sock in ipairs(input) do - self.threads[sock]:resume() - self.threads[sock]:touch() - - if not self.threads[sock]:iswaiting() then - for i, s in ipairs(self.waiting) do - if s == sock then - table.remove(self.waiting, i) - break + for i, sock in ipairs(input) do + local thread = self.threads[sock] + thread:resume() + if thread:isdead() then + self:remove_dead(thread) + else + thread:touch() + + if not thread:iswaiting() then + for i, s in ipairs(self.waiting) do + if s == sock then + table.remove(self.waiting, i) + break + end + end + if not working then + working = true end - end - if not working then - working = true end end end if err == "timeout" and not working then - socket.sleep(self.timeout) + self:kill_timedout() + socket.sleep(self.waittime) end end