Roundup Tracker - Issues

Issue 2551225

classification
Internal errors cause WSGI to exit without calling start_response()
Type: behavior Severity: normal
Components: Web interface Versions: 2.2.0
process
Status: new
:
: rouilj : rouilj, schlatterbeck, tekberg
Priority: normal :

Created on 2022-07-26 19:03 by rouilj, last changed 2022-07-26 19:03 by rouilj.

Messages
msg7620 Author: [hidden] (rouilj) Date: 2022-07-26 19:03
The original report is at:

  https://sourceforge.net/p/roundup/mailman/message/37681135/

Tom ran into an issue where an IOError exception occurring while
running under WSGI caused Apache to log:

   Exception occurred processing WSGI script '../wsgi.py'.
   RuntimeError: response has not been started

(note the error "start_response() not called" is raised as a
ValueError in wsgi_handler.py.)

The exception handling causes
wsgi_handler.py:RequestHandler::start_response to never get called.

The exception handlers in client.py::inner_main() lines 810 or 879 (in
v2.2.0) use:

   except IOError:
       pass

which is intended to ignore a disconnected client.

My initial attempt to reproduce was behind a proxy server. Since the
proxy server handled the client disconnect and was always connected to
the roundup-server processes, I never saw an IOError.

Running python3 roundup/scripts/roundup_server (with python3.9 windows
cygwin) locally and terminating the connection resulted in the
expected traceback. (I added a sleep call inside the start of
inner_main to make the connection long enough to cancel.)

The reported exception (from roundup_server not wsgi) is:

Traceback (most recent call last):
     File "/usr/lib/python3.9/socketserver.py", line 616, in
     process_request
       self.finish_request(request, client_address)
     File "/usr/lib/python3.9/socketserver.py", line 360, in
     finish_request
       self.RequestHandlerClass(request, client_address, self)
     File "/usr/lib/python3.9/socketserver.py", line 747, in __init__
       self.handle()
     File "/usr/lib/python3.9/http/server.py", line 429, in handle
       self.handle_one_request()
     File "/usr/lib/python3.9/http/server.py", line 395, in
     handle_one_request
       self.raw_requestline = self.rfile.readline(65537)
     File "/usr/lib/python3.9/socket.py", line 706, in readinto
       return self._sock.recv_into(b)
     ConnectionAbortedError: [Errno 113] Software caused connection abort

According to the manual 
(https://docs.python.org/3/library/exceptions.html#ConnectionAbortedError)the exception tree 
is:

   OSError (IOError is aliased to OSError in python 3.3+)
     ConnectionError
        ConnectionAbortedError

Also we handle:

        except SysCallError:
            # OpenSSL.SSL.SysCallError is similar to IOError above

similarly when using native SSL IIRC.

So we have a few issues:

  1. the IOError handler under python3 no longer gets triggered for a
     closed client socket that raises ConnectionAbortedError. However
     if I understand the exception hierarchy it should get triggered.
     So maybe I am not testing things correctly?
     
  2. for the error case indicated by the comment, we could specifically
     target ConnectionAbortedError. But ConnectionAbortedError is not
     present under python2. OSError is present under python2, so we
     could in theory use that but I am not sure if it would capture
     more that it should. Also under python2 OSError and IOError are
     subclassed from EnvironmentError, so not replacements.

  3. we could use the more specific 'socket.error' exception. This is
     a subclass of IOError as of python 2.6 or an alias of OSError as
     of python 3.3. My guess is this is what is thrown under python
     2.7 and the IOError handler (if it worked) is really catching
     socket.error.

  4. when modifying the code to implement #3, it looks like the exception
     is not even making it to inner_main or to the top level exception
     handler in roundup_server.py/RoundupRequestHandler::run_cgi().
     So I am not sure where that traceback is being generated.

  5. why does that traceback not have any references to a file in the
     roundup code tree?
  
  6. handling IOError using a 'pass' may be what is needed.


So Ralf any ideas? I know you run wsgi more than I do. To replicate
Tom's issue, it looks like raising an IOError inside of determine_user
should do the trick.
History
Date User Action Args
2022-07-26 19:03:12rouiljcreate