Current Location: Home> Latest Articles> How to determine whether the request has been completed before curl_multi_close

How to determine whether the request has been completed before curl_multi_close

gitbox 2025-05-12

When using the curl_multi_* series of functions to make concurrent requests, we usually open multiple curl handles and add them to a curl_multi handle for unified management.
In order to ensure that all requests have been completed correctly before calling curl_multi_close to release resources, we need to reasonably detect the execution status of each request. This article will explain a standard and reliable way to achieve this requirement.

Basic Process Overview

Usually we follow the following steps to handle multiple requests:

  1. Initialize multiple curl separate handles.

  2. Add these handles to a curl_multi handle.

  3. Continuously execute requests using curl_multi_exec .

  4. Use curl_multi_select to cooperate with curl_multi_exec to detect whether a request has been completed.

  5. Removes completed request handles one by one.

  6. Make sure that all requests are completed, then call curl_multi_close .

Here is a complete example, assuming we need to request multiple URLs (here we take https://gitbox.net/example1 and https://gitbox.net/example2 as examples):

 <?php

// initialization cURL multi Handle
$multiHandle = curl_multi_init();

// Store each cURL Handle的数组
$curlHandles = [];

// To request URL List
$urls = [
    'https://gitbox.net/example1',
    'https://gitbox.net/example2',
];

// Create and add each cURL Handle
foreach ($urls as $i => $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$i] = $ch;
}

// implement multi ask
$running = null;
do {
    $status = curl_multi_exec($multiHandle, $running);

    // prevent CPU Idle
    if ($status == CURLM_OK) {
        curl_multi_select($multiHandle);
    } else {
        break;
    }

    // 检查是否有已完成的ask
    while ($info = curl_multi_info_read($multiHandle)) {
        if ($info['msg'] == CURLMSG_DONE) {
            // 获取完成的Handle
            $completedHandle = $info['handle'];

            // Get the returned content
            $response = curl_multi_getcontent($completedHandle);

            // The returned data can be processed here
            echo "ask完成,Return data length:" . strlen($response) . PHP_EOL;

            // 移除并关闭已完成的Handle
            curl_multi_remove_handle($multiHandle, $completedHandle);
            curl_close($completedHandle);
        }
    }
} while ($running > 0);

// Last Close multi Handle
curl_multi_close($multiHandle);

Key points explanation

  • curl_multi_exec : Promote the execution of concurrent requests and return the number of connections that are still running.

  • curl_multi_select : used to block and wait for active connections to reduce waste of CPU resources.

  • curl_multi_info_read : Detects whether a request has been completed and can process completed handles at one time.

  • curl_multi_close is called only when $running == 0 and all the clone handles have been removed and closed.

Tips

  • If there are many requests, it is recommended to add a timeout mechanism to prevent some requests from getting stuck for a long time.

  • curl_multi_select sometimes returns -1 , in this case, you need to use usleep() for small waits to prevent a dead loop.

Simple processing example of select returning -1 :

 if (curl_multi_select($multiHandle) == -1) {
    usleep(100);
}

This ensures that the script is more robust.

Summarize

Before using curl_multi_close , the key is to confirm that all subrequests have been completed and cleaned correctly. The above pattern is a common and recommended standard practice.
Understanding the behavior of the curl_multi_* series will help write more efficient and stable concurrent network request code!