Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove memoryview usage in urllib3.contrib.pyopenssl#sendall #719

Merged
merged 1 commit into from
Oct 17, 2015

Conversation

evnm
Copy link
Contributor

@evnm evnm commented Oct 15, 2015

As described in #717, urllib3.contrib.pyopenssl#sendall currently fails when WantWriteError is thrown by OpenSSL due to urllib3 preemptively casting the data to be written as a memoryview. This results in duplicate bytestring allocations by pyopenssl and OpenSSL issuing a SSL3_WRITE_PENDING error.

This change removes memoryview usage from urllib3/contrib/pyopenssl.py. We thus rely on the underlying pyOpenSSL library's ability to cast data to the proper bytestring type.

@Lukasa
Copy link
Sponsor Contributor

Lukasa commented Oct 15, 2015

This change looks entirely reasonable to me. I'm going to hold off merging and let @shazow do that, but I don't see any reason he can't. =) Thanks again @evnm!

@shazow
Copy link
Member

shazow commented Oct 17, 2015

Looks swell, thank you for finding it, reporting it, and fixing it! (And to @Lukasa for being Captain Maintainer) 🍮

@ScottEAdams
Copy link

Sadly the lastest dev doesnt fix it for me, only rolling back to 1.10.4 does. Here is the traceback from latest dev on heroku trying to send email via djrill

app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/sessions.py", line 576, in send
app[worker.1]:     r = adapter.send(request, **kwargs)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/adapters.py", line 370, in send
app[worker.1]:     timeout=timeout
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 559, in urlopen
app[worker.1]:     body=body, headers=headers)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 353, in _make_request
app[worker.1]:     conn.request(method, url, **httplib_request_kw)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/httplib.py", line 1053, in request
app[worker.1]:     self._send_request(method, url, body, headers)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/httplib.py", line 1093, in _send_request
app[worker.1]:     self.endheaders(body)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.58.0.43/newrelic/hooks/external_httplib.py", line 35, in httplib_endheaders_wrapper
app[worker.1]:     return wrapped(*args, **kwargs)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/httplib.py", line 1049, in endheaders
app[worker.1]:     self._send_output(message_body)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/httplib.py", line 893, in _send_output
app[worker.1]:     self.send(msg)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/httplib.py", line 869, in send
app[worker.1]:     self.sock.sendall(data)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/packages/urllib3/contrib/pyopenssl.py", line 220, in sendall
app[worker.1]:     sent = self._send_until_done(data[total_sent:total_sent+SSL_WRITE_BLOCKSIZE])
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/requests/packages/urllib3/contrib/pyopenssl.py", line 206, in _send_until_done
app[worker.1]:     return self.connection.send(data)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1271, in send
app[worker.1]:     self._raise_ssl_error(self._ssl, result)
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1187, in _raise_ssl_error
app[worker.1]:     _raise_current_error()
app[worker.1]:   File "/app/.heroku/python/lib/python2.7/site-packages/OpenSSL/_util.py", line 48, in exception_from_error_queue
app[worker.1]:     raise exception_type(errors)
app[worker.1]: Error: [('SSL routines', 'SSL3_WRITE_PENDING', 'bad write retry')]

@Lukasa
Copy link
Sponsor Contributor

Lukasa commented Nov 17, 2015

@7wonders You aren't using the latest master in that traceback. You have a traceback that includes line 220 of urllib3.contrib.pyopenssl, and claims that it's in sendall. In the latest master, line 220 is in close. Want to try again?

@Lukasa
Copy link
Sponsor Contributor

Lukasa commented Nov 17, 2015

In fact, your traceback is substantially identical to the one originally posted in #717, which strongly suggests you were using the flawed version of the code. =)

@ScottEAdams
Copy link

It was very late/early this morning so you might be right and heroku has been known to cache previous versions :) I did however force a full reinstall by switching python versions to be sure caches were cleared and then even opened bash into heroku and checked the urllib3/contrib/pyopenssl.py that the following was gone.

-try:       
-    _ = memoryview     
-    has_memoryview = True      
-except NameError:      
-    has_memoryview = False     
-

And, like I said, as soon as I installled 1.10.4 it was working again. I will have to wait until later to try again as it is only happening under very specific circumstances.

@Lukasa
Copy link
Sponsor Contributor

Lukasa commented Nov 17, 2015

Bear in mind that requests uses its own personal copy of urllib3, and does not use any one that you install from PyPI. This may have caused your misleading result.

@ScottEAdams
Copy link

^^yes. Exactly this. But then why would it work when I switched urllib3 to 1.10.4.

@Lukasa
Copy link
Sponsor Contributor

Lukasa commented Nov 17, 2015

It should be unrelated. Note, however, that this issue is not totally deterministic, and depends how the writes land on the SSL layer.

@ScottEAdams
Copy link

Thanks for the help Lukasa. I will try again later and replace requests with an updated urllib3 fork to test.

fermayo added a commit to tutumcloud/requests that referenced this pull request Nov 24, 2015
@jof
Copy link

jof commented Dec 1, 2015

I'm still running into this issue in the latest version of kennethreitz/requests (2.8.1), which vendors urllib3 into itself.
Since this was fixed since the last release (1.12), there is not yet a newer version to ask requests to vendor, such that it includes the fix.

Might it be possible to cut a release soon so that I can try and get requests rolled forward with this fix included?
cc @shazow

@sjyvmbam
Copy link

As described in #717, urllib3.contrib.pyopenssl#sendall currently fails when WantWriteError is thrown by OpenSSL due to urllib3 preemptively casting the data to be written as a memoryview. This results in duplicate bytestring allocations by pyopenssl and OpenSSL issuing a SSL3_WRITE_PENDING error.

This change removes memoryview usage from urllib3/contrib/pyopenssl.py. We thus rely on the underlying pyOpenSSL library's ability to cast data to the proper bytestring type.

Please how to remove this memoryview ???

@pquentin
Copy link
Member

@sjyvmbam Can you please open a new issue with the actual problem you're facing? We introduced another memoryview in 1.26.0, this six years old pull request is probably not related to your problem.

@sjyvmbam
Copy link

sjyvmbam commented Sep 30, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants