summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfsbs <fsbs@users.noreply.github.com>2021-10-12 14:18:23 +0000
committerfsbs <fsbs@users.noreply.github.com>2021-10-12 16:18:23 +0200
commitddde58832187211e68e04f16a08342b155baab51 (patch)
treeae8c62118378fa627c1289e89f2686ccb2b6a234 /src
parent23afe62edb66a751604974bef5dad63edd79d3de (diff)
downloadpycurl-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
Diffstat (limited to 'src')
-rw-r--r--src/easy.c5
-rw-r--r--src/easyperform.c4
-rw-r--r--src/pycurl.h13
3 files changed, 19 insertions, 3 deletions
diff --git a/src/easy.c b/src/easy.c
index a22ad9c..89d159d 100644
--- a/src/easy.c
+++ b/src/easy.c
@@ -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)