-
Notifications
You must be signed in to change notification settings - Fork 307
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
Assertion failed: self->handle != NULL, file src/threadsupport.c, line 29 #748
Comments
Yeah, a reproducer would be very helpful. If not, you could try bisecting to see which commit introduced the problem. @fsbs any ideas here? |
I'm having trouble writing something standalone to trigger it, the application is pretty big. |
|
Thanks. That was my suspicion. Hopefully @fsbs will have a chance to look into this. |
Sorry, still no luck with a reproducer, I'll have another stab at it tonight. |
@citrus-it did you ever get a reproducer for this? |
Unfortunately not, I'll give it another go this week. Our test suite triggers it every time, but it's a large project so hard to isolate. |
I have a smaller reproducer now, still using a large part of the local application library so I will keep iterating. |
I've been unable to make a standalone reproducer for this, the small-ish script I have still pulls in a lot of modules from the application. However, I can see where the bug is from reading through the code. Here's the relevant piece of the stack trace from the core file, most recent frame first (so read it backwards), with some in-line annotations.
|
Hi, we've hit this as well (apparently in the same application on Oracle Solaris). @citrus-it showed the behavior in the trace above, but here are my notes with some new info from my digging. In our case, the issue arises in Here is what is happening: PYCURL_BEGIN_ALLOW_THREADS_EASY
(void) curl_multi_remove_handle(multi_stack->multi_handle, handle);
PYCURL_END_ALLOW_THREADS_EASY at this point, if (self->multi_stack != NULL && self->multi_stack->state != NULL)
{
/* inside multi_perform() */
assert(self->handle != NULL);
assert(self->multi_stack->multi_handle != NULL);
assert(self->state == NULL);
return self->multi_stack->state;
} where the condition still passes and the assertion fails. When I move When I remove |
As for the possible fix, I tried the following three patches:
--- pycurl-7.45.2/src/easy.c
+++ pycurl-7.45.2/src/easy.c
@@ -469,10 +469,7 @@ util_curl_xdecref(CurlObject *self, int
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);
--- pycurl-7.45.2/src/easy.c
+++ pycurl-7.45.2/src/easy.c
@@ -470,9 +470,13 @@ util_curl_xdecref(CurlObject *self, int
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
+ if (self->handle) {
+ PYCURL_BEGIN_ALLOW_THREADS_EASY
+ (void) curl_multi_remove_handle(multi_stack->multi_handle, handle);
+ PYCURL_END_ALLOW_THREADS_EASY
+ } else {
+ (void) curl_multi_remove_handle(multi_stack->multi_handle, handle);
+ }
}
self->multi_stack = NULL;
Py_DECREF(multi_stack);
--- pycurl-7.45.2/src/easy.c
+++ pycurl-7.45.2/src/easy.c
@@ -567,7 +567,6 @@ util_curl_close(CurlObject *self)
assert(self != NULL);
assert(PyObject_IsInstance((PyObject *) self, (PyObject *) p_Curl_Type) == 1);
handle = self->handle;
- self->handle = NULL;
if (handle == NULL) {
/* Some paranoia assertions just to make sure the object
* deallocation problem is finally really fixed... */
@@ -584,6 +583,7 @@ util_curl_close(CurlObject *self)
/* Decref multi stuff which uses this handle */
util_curl_xdecref(self, PYCURL_MEMGROUP_MULTI, handle);
+ self->handle = NULL;
/* Decref share which uses this handle */
util_curl_xdecref(self, PYCURL_MEMGROUP_SHARE, handle); All three seem to have fixed the original issue we saw in the application. I also ran PycURL test suite and the first two changes caused All that said, I have only very limited knowledge of PycURL (or cURL), so I might be missing important details. |
Thank you very much for your research @citrus-it. |
Hi,
I have upgraded pycurl from 7.44.0 to 7.45.1 and am seeing the above assertion fail when running the testsuite for a large python application that uses pycurl. I am still investigating and trying to write a small reproducer, and I'll attach one once I can, but I'm opening this in case it's immediately obvious to the maintainers or if anyone else is seeing it since upgrading.
What happened?
When running the testsuite with
pycurl.verbose
, this is what I see:The stack trace from the core file is:
so it seems to be being triggered by garbage collection.
What is the PycURL version?
'PycURL/7.45.1 libcurl/7.82.0 OpenSSL/3.0.1 zlib/1.2.11 brotli/1.0.9 zstd/1.5.2 nghttp2/1.47.0'
What is your Python version?
Python 3.10.2
What is your operating system and its version?
OmniOS v11 r151041 SunOS bloody 5.11 omnios-master-57a305f45c i86pc i386 i86pc
The text was updated successfully, but these errors were encountered: