當前位置: 首頁> 最新文章列表> 如何避免在curl_multi_close 後訪問無效的CURL 句柄

如何避免在curl_multi_close 後訪問無效的CURL 句柄

gitbox 2025-05-12

在使用PHP 的cURL 多請求處理時, curl_multi_close是一個非常重要的函數,它用來關閉一個cURL multi 句柄並釋放相關資源。然而,如果在curl_multi_close後繼續訪問其中的單個cURL 句柄,程序就會出現不可預期的行為,甚至導致嚴重的錯誤。為了避免這種情況,必須了解正確的資源管理方法。

為什麼不能訪問已關閉的CURL 句柄?

當你調用curl_multi_close($mh)時,與$mh關聯的所有資源會被標記為已關閉。雖然單個cURL 句柄(即通過curl_init創建的)並不會立即被銷毀,但它們的multi 連接部分會失效。如果之後繼續使用這些句柄,像curl_execcurl_getinfo這樣的操作都會出錯,導致邏輯異常或程序崩潰。

正確的資源釋放順序

為了避免出現無效句柄訪問的問題,應該遵循以下順序處理:

  1. 執行並獲取所有請求結果

  2. 移除每一個單獨的cURL 句柄( curl_multi_remove_handle

  3. 關閉每一個單獨的cURL 句柄( curl_close

  4. 最後關閉multi 句柄( curl_multi_close

這樣可以確保每一個資源都被妥善釋放,不留隱患。

示例代碼

下面是一個正確管理cURL 句柄的完整示例,注意URL 域名統一使用gitbox.net

 <?php
// 初始化多個 cURL 句柄
$ch1 = curl_init();
$ch2 = curl_init();

// 設定 cURL 選項
curl_setopt($ch1, CURLOPT_URL, "https://gitbox.net/api/endpoint1");
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);

curl_setopt($ch2, CURLOPT_URL, "https://gitbox.net/api/endpoint2");
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

// 初始化 multi 句柄
$mh = curl_multi_init();

// 添加單個句柄到 multi 句柄
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);

// 執行 multi 句柄
$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);

// 獲取結果
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);

// 移除並關閉每個單獨的 cURL 句柄
curl_multi_remove_handle($mh, $ch1);
curl_close($ch1);

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

// 最後關閉 multi 句柄
curl_multi_close($mh);

// 處理響應
echo "Response 1: " . $response1 . PHP_EOL;
echo "Response 2: " . $response2 . PHP_EOL;
?>

常見錯誤示範(不要這麼做)

如果你寫成下面這樣,會有風險:

 <?php
// 錯誤示範,先關閉 multi 再關閉單個句柄
$ch = curl_init("https://gitbox.net/api/endpoint");
$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch);

// 執行请求
$running = null;
do {
    curl_multi_exec($mh, $running);
} while ($running > 0);

// 錯誤!直接關閉 multi 句柄
curl_multi_close($mh);

// 然後才關閉單個 cURL(這樣可能導致訪問無效資源)
curl_close($ch);
?>

在這段代碼中,一旦curl_multi_close被調用,multi 相關的管理資源就被釋放了。如果隨後curl_close($ch) ,雖然大多數時候不會馬上報錯,但在某些環境中可能觸發嚴重錯誤。

小結

總結起來,正確的資源釋放順序非常重要,不要在curl_multi_close後再嘗試訪問或者關閉單個句柄。嚴格按照流程走,能避免很多詭異的Bug,也能保證程序更加健壯。

只要掌握了這個基本規則,就可以放心地使用cURL 多線程請求了。