diff options
author | fsbs <fsbs@users.noreply.github.com> | 2021-10-12 14:18:23 +0000 |
---|---|---|
committer | fsbs <fsbs@users.noreply.github.com> | 2021-10-12 16:18:23 +0200 |
commit | ddde58832187211e68e04f16a08342b155baab51 (patch) | |
tree | ae8c62118378fa627c1289e89f2686ccb2b6a234 | |
parent | 23afe62edb66a751604974bef5dad63edd79d3de (diff) | |
download | pycurl-ddde58832187211e68e04f16a08342b155baab51.tar.gz |
Set easy->multi_stack->state for multi's callbacks
This ensures multi's callbacks invoked by some easy functions have
access to thread state.
Fixes callbacks invoked by:
* do_curl_pause
* util_curl_xdecref
-rw-r--r-- | src/easy.c | 5 | ||||
-rw-r--r-- | src/easyperform.c | 4 | ||||
-rw-r--r-- | src/pycurl.h | 13 |
3 files changed, 19 insertions, 3 deletions
@@ -137,14 +137,17 @@ util_curl_xdecref(CurlObject *self, int flags, CURL *handle) /* Decrement refcount for multi_stack. */ if (self->multi_stack != NULL) { CurlMultiObject *multi_stack = self->multi_stack; - self->multi_stack = NULL; if (multi_stack->multi_handle != NULL && handle != NULL) { /* TODO this is where we could remove the easy object from the multi object's easy_object_dict, but this requires us to have a reference to the multi object which right now we don't. */ + /* Allow threads because callbacks can be invoked */ + PYCURL_BEGIN_ALLOW_THREADS_EASY (void) curl_multi_remove_handle(multi_stack->multi_handle, handle); + PYCURL_END_ALLOW_THREADS_EASY } + self->multi_stack = NULL; Py_DECREF(multi_stack); } } diff --git a/src/easyperform.c b/src/easyperform.c index 44f21c0..5326df3 100644 --- a/src/easyperform.c +++ b/src/easyperform.c @@ -100,7 +100,7 @@ do_curl_pause(CurlObject *self, PyObject *args) #ifdef WITH_THREAD /* Save handle to current thread (used as context for python callbacks) */ saved_state = self->state; - PYCURL_BEGIN_ALLOW_THREADS + PYCURL_BEGIN_ALLOW_THREADS_EASY /* We must allow threads here because unpausing a handle can cause some of its callbacks to be invoked immediately, from inside @@ -110,7 +110,7 @@ do_curl_pause(CurlObject *self, PyObject *args) res = curl_easy_pause(self->handle, bitmask); #ifdef WITH_THREAD - PYCURL_END_ALLOW_THREADS + PYCURL_END_ALLOW_THREADS_EASY /* Restore the thread-state to whatever it was on entry */ self->state = saved_state; diff --git a/src/pycurl.h b/src/pycurl.h index 31d1eac..c123468 100644 --- a/src/pycurl.h +++ b/src/pycurl.h @@ -263,6 +263,19 @@ PYCURL_INTERNAL void pycurl_ssl_cleanup(void); # define PYCURL_END_ALLOW_THREADS \ Py_END_ALLOW_THREADS \ self->state = NULL; +# define PYCURL_BEGIN_ALLOW_THREADS_EASY \ + if (self->multi_stack == NULL) { \ + self->state = PyThreadState_Get(); \ + assert(self->state != NULL); \ + } else { \ + self->multi_stack->state = PyThreadState_Get(); \ + assert(self->multi_stack->state != NULL); \ + } \ + Py_BEGIN_ALLOW_THREADS +# define PYCURL_END_ALLOW_THREADS_EASY \ + PYCURL_END_ALLOW_THREADS \ + if (self->multi_stack != NULL) \ + self->multi_stack->state = NULL; #else # define PYCURL_DECLARE_THREAD_STATE # define PYCURL_ACQUIRE_THREAD() (1) |