pyca / pyopenssl

A Python wrapper around the OpenSSL library
https://pyopenssl.org/
Apache License 2.0
891 stars 419 forks source link

bio_read raises WantReadError #887

Open denisenkom opened 4 years ago

denisenkom commented 4 years ago

Hi, I am maintaining pytds package. I use pyopenssl to implement TLS connectivity. I got this error report from multiple users: https://github.com/denisenkom/pytds/issues/106. Here is the stack trace:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/pytds/tls.py", line 144, in establish_channel
    conn.do_handshake()
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1915, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1622, in _raise_ssl_error
    raise WantReadError()
OpenSSL.SSL.WantReadError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Volumes/D/repos/tests/deps/pytds_fetch.py", line 75, in <module>
    test_pytds_conn()
  File "/Volumes/D/repos/tests/deps/pytds_fetch.py", line 56, in test_pytds_conn
    tds_version=tds_base.TDS74) as conn:
  File "/usr/local/lib/python3.7/site-packages/pytds/__init__.py", line 1330, in connect
    conn._open()
  File "/usr/local/lib/python3.7/site-packages/pytds/__init__.py", line 371, in _open
    self._try_open(timeout=retry_time)
  File "/usr/local/lib/python3.7/site-packages/pytds/__init__.py", line 353, in _try_open
    self._connect(host=host, port=port, instance=instance, timeout=timeout)
  File "/usr/local/lib/python3.7/site-packages/pytds/__init__.py", line 303, in _connect
    route = conn.login(login, sock, self._tzinfo_factory)
  File "/usr/local/lib/python3.7/site-packages/pytds/tds.py", line 1703, in login
    self._main_session.process_prelogin(login)
  File "/usr/local/lib/python3.7/site-packages/pytds/tds.py", line 1294, in process_prelogin
    self.parse_prelogin(octets=p, login=login)
  File "/usr/local/lib/python3.7/site-packages/pytds/tds.py", line 1339, in parse_prelogin
    tls.establish_channel(self)
  File "/usr/local/lib/python3.7/site-packages/pytds/tls.py", line 147, in establish_channel
    req = conn.bio_read(BUFSIZE)
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1870, in bio_read
    self._handle_bio_errors(self._from_ssl, result)
  File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1835, in _handle_bio_errors
    raise WantReadError()
OpenSSL.SSL.WantReadError

The problem seems to be that bio_read is raising WantReadError exception, which is not supposed to happen, if I understand correctly. bio_read is what you should call when you get WantReadError.

So my question is, is it a bug in pyopenssl that bio_read raises WantReadError? If it is normal for bio_read to raise WantReadError, how should I handle such exception?

graingert commented 2 months ago

this is intentional WantReadError means the openssl object needs more data from your socket - so you need to call bio_write