hypercorn icon indicating copy to clipboard operation
hypercorn copied to clipboard

SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY

Open FelixFunk opened this issue 1 year ago • 4 comments
trafficstars

Apparently the SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY still exists with hypercorn 0.17.3 and python 3.11.5 (as well as 3.12.7).

Closing a running hypercorn instance with ctr-c or any other SIGTERM will (most of the time) result in "ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2706)". In my particular case i ran hypercorn run_service:quart_app -w 3 --graceful-timeout 10 -b 0.0.0.0:44444 --certfile ../dev/ssl/cert.pem --keyfile ../dev/ssl/key.pem --keyfile-password test and got

File ".venv/lib/python3.11/site-packages/hypercorn/asyncio/run.py", line 110, in _server_callback
    await TCPServer(app, loop, config, context, lifespan_state, reader, writer)
  File ".venv/lib/python3.11/site-packages/hypercorn/asyncio/tcp_server.py", line 76, in run
    await self._close()
  File ".venv/lib/python3.11/site-packages/hypercorn/asyncio/tcp_server.py", line 119, in _close
    await self.writer.wait_closed()
  File "/usr/local/anaconda3/lib/python3.11/asyncio/streams.py", line 350, in wait_closed
    await self._protocol._get_close_waiter(self)
  File "/usr/local/anaconda3/lib/python3.11/asyncio/sslproto.py", line 644, in _do_shutdown
    self._sslobj.unwrap()
  File "/usr/local/anaconda3/lib/python3.11/ssl.py", line 983, in unwrap
    return self._sslobj.shutdown()
           ^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2706)

Not sure if it is related to this old issue.

If i missed something in the server configuration to avoid this error please let me know.

FelixFunk avatar Oct 10 '24 15:10 FelixFunk

Python 3.12.3 Hypercorn 0.17.3 Quart 0.19.6

click to show terminal output
(venv) znote@Froeya:~/Projects/HIMS$ python3 run.py 
 * Serving Quart app 'app.app'
 * Debug mode: True
 * Please use an ASGI server (e.g. Hypercorn) directly in production
 * Running on https://0.0.0.0:5000 (CTRL + C to quit)
[2024-10-22 23:52:46 +0200] [168718] [INFO] Running on https://0.0.0.0:5000 (CTRL + C to quit)
[2024-10-22 23:52:51 +0200] [168718] [INFO] 127.0.0.1:34254 GET /qr/ 2 200 285 3582
Unhandled exception in client_connected_cb
handle_traceback: Handle created at (most recent call last):
  File "/home/znote/Projects/HIMS/run.py", line 4, in <module>
    app.run(host='0.0.0.0', port=5000, debug=True, certfile='ssl_keys/app.crt', keyfile='ssl_keys/app.key')
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/quart/app.py", line 852, in run
    loop.run_until_complete(asyncio.gather(*tasks))
  File "/usr/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 641, in run_forever
    self._run_once()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 1979, in _run_once
    handle._run()
  File "/usr/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
transport: <asyncio.sslproto._SSLProtocolTransport object at 0x79f5cd59b950>
Traceback (most recent call last):
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/run.py", line 110, in _server_callback
    await TCPServer(app, loop, config, context, lifespan_state, reader, writer)
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 76, in run
    await self._close()
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 119, in _close
    await self.writer.wait_closed()
  File "/usr/lib/python3.12/asyncio/streams.py", line 364, in wait_closed
    await self._protocol._get_close_waiter(self)
  File "/usr/lib/python3.12/asyncio/sslproto.py", line 648, in _do_shutdown
    self._sslobj.unwrap()
  File "/usr/lib/python3.12/ssl.py", line 921, in unwrap
    return self._sslobj.shutdown()
           ^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2685)

[2024-10-22 23:53:26 +0200] [168718] [INFO] 127.0.0.1:42346 GET /qr/scan 2 200 667 3092
[2024-10-22 23:53:26 +0200] [168718] [INFO] 127.0.0.1:42346 GET /static/html5-qrcode.min.js 2 200 375364 40740
[2024-10-22 23:53:28 +0200] [168718] [INFO] 127.0.0.1:42346 GET / 2 200 116 3335
Unhandled exception in client_connected_cb
handle_traceback: Handle created at (most recent call last):
  File "/home/znote/Projects/HIMS/run.py", line 4, in <module>
    app.run(host='0.0.0.0', port=5000, debug=True, certfile='ssl_keys/app.crt', keyfile='ssl_keys/app.key')
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/quart/app.py", line 852, in run
    loop.run_until_complete(asyncio.gather(*tasks))
  File "/usr/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 641, in run_forever
    self._run_once()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 1979, in _run_once
    handle._run()
  File "/usr/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
transport: <asyncio.sslproto._SSLProtocolTransport object at 0x79f5ccb01010>
Traceback (most recent call last):
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/run.py", line 110, in _server_callback
    await TCPServer(app, loop, config, context, lifespan_state, reader, writer)
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 76, in run
    await self._close()
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 119, in _close
    await self.writer.wait_closed()
  File "/usr/lib/python3.12/asyncio/streams.py", line 364, in wait_closed
    await self._protocol._get_close_waiter(self)
  File "/usr/lib/python3.12/asyncio/sslproto.py", line 648, in _do_shutdown
    self._sslobj.unwrap()
  File "/usr/lib/python3.12/ssl.py", line 921, in unwrap
    return self._sslobj.shutdown()
           ^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2685)

[2024-10-22 23:53:34 +0200] [168718] [INFO] 127.0.0.1:41024 GET /qr/ 2 200 285 2281
[2024-10-22 23:53:36 +0200] [168718] [INFO] 127.0.0.1:41024 GET /qr/scan 2 200 667 3352
[2024-10-22 23:53:39 +0200] [168718] [INFO] 127.0.0.1:41024 GET / 2 200 116 3398
Unhandled exception in client_connected_cb
handle_traceback: Handle created at (most recent call last):
  File "/home/znote/Projects/HIMS/run.py", line 4, in <module>
    app.run(host='0.0.0.0', port=5000, debug=True, certfile='ssl_keys/app.crt', keyfile='ssl_keys/app.key')
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/quart/app.py", line 852, in run
    loop.run_until_complete(asyncio.gather(*tasks))
  File "/usr/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 641, in run_forever
    self._run_once()
  File "/usr/lib/python3.12/asyncio/base_events.py", line 1979, in _run_once
    handle._run()
  File "/usr/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
transport: <asyncio.sslproto._SSLProtocolTransport object at 0x79f5ccb07110>
Traceback (most recent call last):
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/run.py", line 110, in _server_callback
    await TCPServer(app, loop, config, context, lifespan_state, reader, writer)
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 76, in run
    await self._close()
  File "/home/znote/Projects/HIMS/venv/lib/python3.12/site-packages/hypercorn/asyncio/tcp_server.py", line 119, in _close
    await self.writer.wait_closed()
  File "/usr/lib/python3.12/asyncio/streams.py", line 364, in wait_closed
    await self._protocol._get_close_waiter(self)
  File "/usr/lib/python3.12/asyncio/sslproto.py", line 648, in _do_shutdown
    self._sslobj.unwrap()
  File "/usr/lib/python3.12/ssl.py", line 921, in unwrap
    return self._sslobj.shutdown()
           ^^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2685)

I had to generate a self signed certificate without a PEM password just so it wouldn't hang up on me. Although these errors happen, the requests seemingly load and work fine.

For me (using quart dev mode) this would happen with a coin-toss probability at the end of a request, and if my cert isn't password protected would reinitialize by next request continue working. (at a first glance, haven't properly tested this out)

I'm still not convinced that this isn't a bug made by me, new with async code so might have forgotten to await something. Perhaps I should use @app.teardown_appcontext and let ssl close gracefully somehow.

Znote avatar Oct 23 '24 00:10 Znote

As @cjavad mentioned above, I get the same error exactly 5 seconds after the request, using a basic Quart example on Windows 11, Py 3.13.0.

stevstrong avatar Oct 26 '24 13:10 stevstrong

Minimal repo here: https://github.com/cjavad/python-hypercorn-issue-125981-repo

cjavad avatar Oct 26 '24 15:10 cjavad

Is there a way to work around this to not make this so painful while testing websites from the browser?

fersarr avatar Apr 21 '25 21:04 fersarr