Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-99108: Release the GIL around hashlib built-in computation#104675
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
73094a1621f9a64cf2a1988f190fc8e0b0128300280e60cecFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| We now release the GIL around built-in :mod:`hashlib` computations of | ||
| reasonable size for the SHA families and MD5 hash functions, matching | ||
| what our OpenSSL backed hash computations already does. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -49,7 +49,9 @@ typedef long long MD5_INT64; /* 64-bit integer */ | ||
| typedef struct { | ||
| PyObject_HEAD | ||
| // Prevents undefined behavior via multiple threads entering the C API. | ||
| // The lock will be NULL before threaded access has been enabled. | ||
| PyThread_type_lock lock; | ||
| Hacl_Streaming_MD5_state *hash_state; | ||
| } MD5object; | ||
| @@ -72,6 +74,7 @@ static MD5object * | ||
| newMD5object(MD5State * st) | ||
| { | ||
| MD5object *md5 = (MD5object *)PyObject_GC_New(MD5object, st->md5_type); | ||
| md5->lock = NULL; | ||
gpshead marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| PyObject_GC_Track(md5); | ||
| return md5; | ||
| } | ||
| @@ -88,6 +91,9 @@ static void | ||
| MD5_dealloc(MD5object *ptr) | ||
| { | ||
| Hacl_Streaming_MD5_legacy_free(ptr->hash_state); | ||
| if (ptr->lock != NULL) { | ||
| PyThread_free_lock(ptr->lock); | ||
| } | ||
| PyTypeObject *tp = Py_TYPE(ptr); | ||
| PyObject_GC_UnTrack(ptr); | ||
| PyObject_GC_Del(ptr); | ||
| @@ -115,7 +121,9 @@ MD5Type_copy_impl(MD5object *self, PyTypeObject *cls) | ||
| if ((newobj = newMD5object(st))==NULL) | ||
| return NULL; | ||
| ENTER_HASHLIB(self); | ||
| newobj->hash_state = Hacl_Streaming_MD5_legacy_copy(self->hash_state); | ||
| LEAVE_HASHLIB(self); | ||
| return (PyObject *)newobj; | ||
| } | ||
| @@ -130,7 +138,9 @@ MD5Type_digest_impl(MD5object *self) | ||
| /*[clinic end generated code: output=eb691dc4190a07ec input=bc0c4397c2994be6]*/ | ||
| { | ||
| unsigned char digest[MD5_DIGESTSIZE]; | ||
| ENTER_HASHLIB(self); | ||
| Hacl_Streaming_MD5_legacy_finish(self->hash_state, digest); | ||
| LEAVE_HASHLIB(self); | ||
| return PyBytes_FromStringAndSize((const char *)digest, MD5_DIGESTSIZE); | ||
| } | ||
| @@ -145,7 +155,9 @@ MD5Type_hexdigest_impl(MD5object *self) | ||
| /*[clinic end generated code: output=17badced1f3ac932 input=b60b19de644798dd]*/ | ||
| { | ||
| unsigned char digest[MD5_DIGESTSIZE]; | ||
| ENTER_HASHLIB(self); | ||
| Hacl_Streaming_MD5_legacy_finish(self->hash_state, digest); | ||
| LEAVE_HASHLIB(self); | ||
| return _Py_strhex((const char*)digest, MD5_DIGESTSIZE); | ||
| } | ||
| @@ -177,7 +189,18 @@ MD5Type_update(MD5object *self, PyObject *obj) | ||
| GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); | ||
| update(self->hash_state, buf.buf, buf.len); | ||
| if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { | ||
| self->lock = PyThread_allocate_lock(); | ||
| } | ||
| if (self->lock != NULL) { | ||
| Py_BEGIN_ALLOW_THREADS | ||
| PyThread_acquire_lock(self->lock, 1); | ||
gpshead marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| update(self->hash_state, buf.buf, buf.len); | ||
| PyThread_release_lock(self->lock); | ||
| Py_END_ALLOW_THREADS | ||
| } else { | ||
| update(self->hash_state, buf.buf, buf.len); | ||
| } | ||
| PyBuffer_Release(&buf); | ||
| Py_RETURN_NONE; | ||
| @@ -279,7 +302,15 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity) | ||
| return NULL; | ||
| } | ||
| if (string) { | ||
| update(new->hash_state, buf.buf, buf.len); | ||
| if (buf.len >= HASHLIB_GIL_MINSIZE) { | ||
gpshead marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /* We do not initialize self->lock here as this is the constructor | ||
| * where it is not yet possible to have concurrent access. */ | ||
| Py_BEGIN_ALLOW_THREADS | ||
| update(new->hash_state, buf.buf, buf.len); | ||
| Py_END_ALLOW_THREADS | ||
| } else { | ||
| update(new->hash_state, buf.buf, buf.len); | ||
| } | ||
| PyBuffer_Release(&buf); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.