After adding the Start/Poll method I setup some tests to see if other code could run even if there were no requests coming in. Unfortunately, that wasn't the case. Digging into it deeper I discovered that socket.accept() method is blocking by default.
Modifying the example code with a simple print will show the issue.
while True:
try:
print("Processing before polling...")
server.poll()
print("Processing after polling...")
except OSError:
continue
The code will stop at the server.poll() method waiting for a request to come in...
Listening on http://192.168.1.208:80
Processing before polling...
Once a request comes in the other lines will process, then it'll stop at server.poll() again...
Processing after polling...
Processing before polling...
To fix this the socket needs to set blocking to False or it's timeout to 0 in HTTPServer.Start()...
self._sock.bind((host, port))
self._sock.listen(5)
self._sock.setblocking(False) #do not block
There is one caveat to this. When the accept() method doesn't find any incoming connections and blocking is turned off, it raises an exception OSError [Errno 11] EAGAIN. Therefore, server.poll() must be the last thing in the while loop otherwise, the exception will skip any logic after the exception is raised. Which means any logic after server.poll() will only run once a request has been received and processed successfully...
while True:
try:
print("Processing before polling...")
server.poll()
print("Processing after polling...") #This will never be called if exception is raised.
except OSError:
continue
Results in this output...
Listening on http://192.168.1.208:80
Processing before polling...
Processing before polling...
Processing before polling...
Processing before polling...
Received 485 bytes
Processing after polling...
Processing before polling...
Processing before polling...
... and so on
A possible work around for this would be to handle the specific exception OSError: [Errno 11] EAGAIN in the server.poll() method. But I'm not sure if catching and handling exceptions in library code is an acceptable practice.
After adding the Start/Poll method I setup some tests to see if other code could run even if there were no requests coming in. Unfortunately, that wasn't the case. Digging into it deeper I discovered that
socket.accept()
method is blocking by default.Modifying the example code with a simple print will show the issue.
The code will stop at the
server.poll()
method waiting for a request to come in...Once a request comes in the other lines will process, then it'll stop at
server.poll()
again...To fix this the socket needs to set blocking to False or it's timeout to 0 in
HTTPServer.Start()
...There is one caveat to this. When the accept() method doesn't find any incoming connections and blocking is turned off, it raises an exception
OSError [Errno 11] EAGAIN
. Therefore,server.poll()
must be the last thing in the while loop otherwise, the exception will skip any logic after the exception is raised. Which means any logic afterserver.poll()
will only run once a request has been received and processed successfully...Results in this output...
A possible work around for this would be to handle the specific exception
OSError: [Errno 11] EAGAIN
in theserver.poll()
method. But I'm not sure if catching and handling exceptions in library code is an acceptable practice.