Current Location: Home> Latest Articles> How to avoid connection status exceptions after curl_multi_close

How to avoid connection status exceptions after curl_multi_close

gitbox 2025-05-12

The curl_multi_* series functions are very important tools when using PHP's cURL extension for concurrent requests. curl_multi_close is responsible for closing a cURL multi handle , but if used improperly, it can easily lead to abnormal connection status, such as: some requests are not completed, resources are not released correctly, and inexplicable timeouts occur. So, how can we avoid these exceptions gracefully and correctly? This article will explain in detail.

Common Errors

When many developers process concurrent requests, the code may look like this:

 <?php
$mh = curl_multi_init();
$ch1 = curl_init('https://gitbox.net/api/endpoint1');
$ch2 = curl_init('https://gitbox.net/api/endpoint2');

curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// Start and execute
do {
    $status = curl_multi_exec($mh, $active);
    curl_multi_select($mh);
} while ($active && $status == CURLM_OK);

// Close directly
curl_multi_close($mh);

The problem with this writing method is that even if the request has not been fully processed (especially when the network conditions are poor), curl_multi_close is called directly, which will cause some connections to be terminated roughly, and as a result, a state abnormality will naturally occur.

The correct way to do it

Before calling curl_multi_close , you should make sure that all handles ( cURL handle ) have been processed and they are removed! The correct process should be:

  1. Curl_multi_exec is called repeatedly until all requests are completed.

  2. Removes each individual cURL handle ( curl_multi_remove_handle ).

  3. Close a single cURL handle ( curl_close ) separately.

  4. Finally, close multi handle ( curl_multi_close ).

The modified code example is as follows:

 <?php
$mh = curl_multi_init();
$ch1 = curl_init('https://gitbox.net/api/endpoint1');
$ch2 = curl_init('https://gitbox.net/api/endpoint2');

curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// Start and execute
do {
    $status = curl_multi_exec($mh, $active);
    if ($active) {
        curl_multi_select($mh);
    }
} while ($active && $status == CURLM_OK);

// Remove and close a single handle
curl_multi_remove_handle($mh, $ch1);
curl_close($ch1);

curl_multi_remove_handle($mh, $ch2);
curl_close($ch2);

// Last Close multi handle
curl_multi_close($mh);

Pay attention to details

  • curl_multi_remove_handle must be done before curl_multi_close .

  • Even if the connection failed to request, it must be cleaned correctly through remove_handle + close .

  • Using curl_multi_select in a loop can reduce CPU usage and avoid busy waiting.

  • Try to catch errors (such as curl_errno and curl_error ), and do not blindly trust the request to succeed.

Summarize

In high concurrency scenarios, details determine success or failure. The essence of curl_multi_close is just to destroy the multi handle, which itself does not and cannot guarantee the secure closing of all single connections. Therefore, before closing the multi handle, be sure to manually remove and close each individual handle , which is the key to avoiding connection status exceptions.

Following the correct processing process can enable your concurrent requests to run stably and efficiently, away from those headache-prone hidden bugs.