You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue expands on issue #65, which noted a memory issue. This is an explanation for the memory leak and why the suggested unset() won't fix it. Additionally, the original poster's solution of manually calling close() won't prevent the memory leak in PHP8+.
Minimum reproducible code:
$curl = new Curl\Curl();
unset($curl); // destructor not called; object still in memory
In short, the destructor is never being called. Even if you manually unset() the object, the destructor will not be called. This means the object is never garbage collected, the curl resource is never closed, and the memory is never cleaned up, until the end of the script.
The destructor method will be called as soon as there are no other references to a particular object...
The reason the destructor is not called is because there is a circular reference between the Curl object and the underlying curl resource. The Curl constructor calls the init() function, and the init() function has this line:
The Curl object has a reference to the curl resource, and now, because of that line, the curl resource has a reference to the Curl object.
Therefore, when you call unset($curl) in the code above, the variable will be unset, but the object will not actually be destroyed because the curl resource still has a reference to it.
This is why manually calling the close() method removes the memory leak (at least before PHP8). When the close() method is called, it closes the curl resource, which removes the reference to the Curl object, leaving the only reference being the one we created. Therefore, when we unset our reference (or our reference goes out of scope), there will be no more references and the object can be destroyed.
curl_init() will now return a CurlHandle object rather than a resource. The curl_close() function no longer has an effect, instead the CurlHandle instance is automatically destroyed if it is no longer referenced.
In PHP8, the curl functions were changed to operate on a CurlHandle object instead of a curl resource. Additionally, the curl_close() function was updated to have no effect. Therefore, in PHP8, manually calling the close() method will not resolve the memory leak because it doesn't actually do anything. The circular reference between the Curl object and the CurlHandle object will still exist.
The easiest solution would be to remove the line from the init() function and add it into the exec() function, so you can set it before the curl request and then unset it after the curl request:
This issue expands on issue #65, which noted a memory issue. This is an explanation for the memory leak and why the suggested
unset()
won't fix it. Additionally, the original poster's solution of manually callingclose()
won't prevent the memory leak in PHP8+.Minimum reproducible code:
In short, the destructor is never being called. Even if you manually
unset()
the object, the destructor will not be called. This means the object is never garbage collected, the curl resource is never closed, and the memory is never cleaned up, until the end of the script.From the PHP manual:
The reason the destructor is not called is because there is a circular reference between the Curl object and the underlying curl resource. The Curl constructor calls the
init()
function, and theinit()
function has this line:The Curl object has a reference to the curl resource, and now, because of that line, the curl resource has a reference to the Curl object.
Therefore, when you call
unset($curl)
in the code above, the variable will be unset, but the object will not actually be destroyed because the curl resource still has a reference to it.This is why manually calling the
close()
method removes the memory leak (at least before PHP8). When theclose()
method is called, it closes the curl resource, which removes the reference to the Curl object, leaving the only reference being the one we created. Therefore, when we unset our reference (or our reference goes out of scope), there will be no more references and the object can be destroyed.However, this is not true in PHP8. From the PHP8 migration guide:
In PHP8, the curl functions were changed to operate on a CurlHandle object instead of a curl resource. Additionally, the
curl_close()
function was updated to have no effect. Therefore, in PHP8, manually calling theclose()
method will not resolve the memory leak because it doesn't actually do anything. The circular reference between the Curl object and the CurlHandle object will still exist.The easiest solution would be to remove the line from the
init()
function and add it into theexec()
function, so you can set it before the curl request and then unset it after the curl request:Thanks,
Patrick
The text was updated successfully, but these errors were encountered: