Prevent cURL transport from leaking on Exception#319
Prevent cURL transport from leaking on Exception#319soulseekah wants to merge 10 commits intoWordPress:developfrom
Conversation
|
Calling Requesting a bad URL, even if it's a mere certificate error, will not call the destructor and eventually
Breaking case: while(true) {
try {
$response = Requests::post('http://localhost:43992', array(), array(), array('transport'=>'Requests_Transport_cURL'));
} catch (Exception $e) {}
}Where http://localhost:43992 is a nonexistent local endpoint (to error out faster). |
|
Leaks exception for me too: Trying to catch is unsuccessful |
|
There is one big problem with the fix proposed here: A better fix will be: try
{
$this->process_response($response, $options);
}
finally
{
if (true === $options['blocking'])
{
// Need to remove the $this reference from the curl handle.
// Otherwise Requests_Transport_cURL wont be garbage collected and the curl_close() will never be called.
curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null);
curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null);
}
} |
|
As we have now moved to PHP 5.6 as a minimum requirement, it seems to make sense to take a fresh look at the execution flow, and use the |
|
Note for the next iteration of this PR: For testing the correct functioning of this change, the PHPUnit 9.3+ Also note: tests are only relevant for PHP < 8.0 and should be skipped on PHP 8.0+ as Curl was changed from using resources to using objects. |
9771abb to
3d91340
Compare
1614444 to
e127137
Compare
|
Tests are failing because PHP 7 does check for active references to a resource before closing it, even if you explicitly use In our case, the very fact that we want to test whether the resource is closed properly creates a reference to the resource. So while there is no memory leak in the normal code path, there is one in the test - because of the test. The only way I can think of for solving this is by using weak references, but those have only been introduced with PHP 7.2. Options right now:
|
The `CURLOPT_HEADERFUNCTION` and `CURLOPT_WRITEFUNCTION` options are not being reset if a cURL handle error occurs (which throws a `Requests_Exception` and stops execution). The destructor is not called due to lingering instance method callbacks in the two options. Move `CURLOPT_HEADERFUNCTION` and `CURLOPT_WRITEFUNCTION` cleanup before any exceptions can happen.
e127137 to
a154c56
Compare
a154c56 to
dd91131
Compare
81ba36f to
61b3b14
Compare
|
Okay, so I have spend some time today trying to create a better/working test for this. Current status can be seen here: https://github.com/WordPress/Requests/tree/319/better-test-attempt-take-two Tentative conclusions:
|
The
CURLOPT_HEADERFUNCTIONandCURLOPT_WRITEFUNCTIONoptions are notbeing reset if a cURL handle error occurs (which throws a
Requests_Exceptionand stops execution). The destructor is not calleddue to lingering instance method callbacks in the two options.
Move
CURLOPT_HEADERFUNCTIONandCURLOPT_WRITEFUNCTIONcleanup beforeany exceptions can happen.