1 import sys, os, threading, time, logging, select
4 log = logging.getLogger("ashd.serve")
6 seqlk = threading.Lock()
15 class closed(IOError):
17 super().__init__("The client has closed the connection.")
19 class reqthread(threading.Thread):
20 def __init__(self, *, name=None, **kw):
22 name = "Request handler %i" % reqseq()
23 super().__init__(name=name, **kw)
25 class wsgirequest(object):
26 def __init__(self, handler):
30 self.handler = handler
31 self.buffer = bytearray()
37 def writehead(self, status, headers):
43 def writedata(self, data):
44 self.buffer.extend(data)
49 raise Exception("Cannot send response body before starting response.")
51 self.writehead(self.status, self.headers)
53 def write(self, data):
58 self.handler.ckflush(self)
60 def startreq(self, status, headers, exc_info=None):
69 raise Exception("Can only start responding once.")
71 self.headers = headers
74 class handler(object):
75 def handle(self, request):
77 def ckflush(self, req):
82 class freethread(handler):
83 def __init__(self, **kw):
84 super().__init__(**kw)
86 self.lk = threading.Lock()
88 def handle(self, req):
89 reqthread(target=self.run, args=[req]).start()
91 def ckflush(self, req):
92 while len(req.buffer) > 0:
93 rls, wls, els = select.select([], [req], [req])
98 th = threading.current_thread()
103 with perf.request(env) as reqevent:
104 respiter = req.handlewsgi(env, req.startreq)
105 for data in respiter:
108 reqevent.response([req.status, req.headers])
114 log.error("exception occurred when handling request", exc_info=True)
117 self.current.remove(th)
124 if len(self.current) > 0:
125 th = next(iter(self.current))
130 names = {"free": freethread}