@@ -106,7 +106,9 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
106
106
if (0 < $ duration ) {
107
107
if ($ execCounter === $ multi ->execCounter ) {
108
108
$ multi ->execCounter = !\is_float ($ execCounter ) ? 1 + $ execCounter : \PHP_INT_MIN ;
109
- curl_multi_remove_handle ($ multi ->handle , $ ch );
109
+ foreach ($ multi ->handles as $ mh ) {
110
+ curl_multi_remove_handle ($ mh , $ ch );
111
+ }
110
112
}
111
113
112
114
$ lastExpiry = end ($ multi ->pauseExpiries );
@@ -118,7 +120,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
118
120
} else {
119
121
unset($ multi ->pauseExpiries [(int ) $ ch ]);
120
122
curl_pause ($ ch , \CURLPAUSE_CONT );
121
- curl_multi_add_handle ($ multi ->handle , $ ch );
123
+ curl_multi_add_handle ($ multi ->handles [ 0 ] , $ ch );
122
124
}
123
125
};
124
126
@@ -172,7 +174,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
172
174
// Schedule the request in a non-blocking way
173
175
$ multi ->lastTimeout = null ;
174
176
$ multi ->openHandles [$ id ] = [$ ch , $ options ];
175
- curl_multi_add_handle ($ multi ->handle , $ ch );
177
+ curl_multi_add_handle ($ multi ->handles [ 0 ] , $ ch );
176
178
177
179
$ this ->canary = new Canary (static function () use ($ ch , $ multi , $ id ) {
178
180
unset($ multi ->pauseExpiries [$ id ], $ multi ->openHandles [$ id ], $ multi ->handlesActivity [$ id ]);
@@ -182,7 +184,9 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
182
184
return ;
183
185
}
184
186
185
- curl_multi_remove_handle ($ multi ->handle , $ ch );
187
+ foreach ($ multi ->handles as $ mh ) {
188
+ curl_multi_remove_handle ($ mh , $ ch );
189
+ }
186
190
curl_setopt_array ($ ch , [
187
191
\CURLOPT_NOPROGRESS => true ,
188
192
\CURLOPT_PROGRESSFUNCTION => null ,
@@ -264,7 +268,7 @@ public function __destruct()
264
268
*/
265
269
private static function schedule (self $ response , array &$ runningResponses ): void
266
270
{
267
- if (isset ($ runningResponses [$ i = (int ) $ response ->multi ->handle ])) {
271
+ if (isset ($ runningResponses [$ i = (int ) $ response ->multi ->handles [ 0 ] ])) {
268
272
$ runningResponses [$ i ][1 ][$ response ->id ] = $ response ;
269
273
} else {
270
274
$ runningResponses [$ i ] = [$ response ->multi , [$ response ->id => $ response ]];
@@ -297,38 +301,47 @@ private static function perform(ClientState $multi, array &$responses = null): v
297
301
try {
298
302
self ::$ performing = true ;
299
303
++$ multi ->execCounter ;
300
- $ active = 0 ;
301
- while (\CURLM_CALL_MULTI_PERFORM === ($ err = curl_multi_exec ($ multi ->handle , $ active )));
302
-
303
- if (\CURLM_OK !== $ err ) {
304
- throw new TransportException (curl_multi_strerror ($ err ));
305
- }
306
304
307
- while ($ info = curl_multi_info_read ( $ multi -> handle ) ) {
308
- if (\ CURLMSG_DONE !== $ info [ ' msg ' ]) {
309
- continue ;
305
+ foreach ($ multi -> handles as $ i => $ mh ) {
306
+ $ active = 0 ;
307
+ while (\ CURLM_CALL_MULTI_PERFORM === ( $ err = curl_multi_exec ( $ mh , $ active ))) {
310
308
}
311
- $ result = $ info ['result ' ];
312
- $ id = (int ) $ ch = $ info ['handle ' ];
313
- $ waitFor = @curl_getinfo ($ ch , \CURLINFO_PRIVATE ) ?: '_0 ' ;
314
309
315
- if (\in_array ($ result , [\CURLE_SEND_ERROR , \CURLE_RECV_ERROR , /*CURLE_HTTP2*/ 16 , /*CURLE_HTTP2_STREAM*/ 92 ], true ) && $ waitFor [1 ] && 'C ' !== $ waitFor [0 ]) {
316
- curl_multi_remove_handle ($ multi ->handle , $ ch );
317
- $ waitFor [1 ] = (string ) ((int ) $ waitFor [1 ] - 1 ); // decrement the retry counter
318
- curl_setopt ($ ch , \CURLOPT_PRIVATE , $ waitFor );
319
- curl_setopt ($ ch , \CURLOPT_FORBID_REUSE , true );
310
+ if (\CURLM_OK !== $ err ) {
311
+ throw new TransportException (curl_multi_strerror ($ err ));
312
+ }
320
313
321
- if (0 === curl_multi_add_handle ($ multi ->handle , $ ch )) {
314
+ while ($ info = curl_multi_info_read ($ mh )) {
315
+ if (\CURLMSG_DONE !== $ info ['msg ' ]) {
322
316
continue ;
323
317
}
324
- }
318
+ $ result = $ info ['result ' ];
319
+ $ id = (int ) $ ch = $ info ['handle ' ];
320
+ $ waitFor = @curl_getinfo ($ ch , \CURLINFO_PRIVATE ) ?: '_0 ' ;
321
+
322
+ if (\in_array ($ result , [\CURLE_SEND_ERROR , \CURLE_RECV_ERROR , /*CURLE_HTTP2*/ 16 , /*CURLE_HTTP2_STREAM*/ 92 ], true ) && $ waitFor [1 ] && 'C ' !== $ waitFor [0 ]) {
323
+ curl_multi_remove_handle ($ mh , $ ch );
324
+ $ waitFor [1 ] = (string ) ((int ) $ waitFor [1 ] - 1 ); // decrement the retry counter
325
+ curl_setopt ($ ch , \CURLOPT_PRIVATE , $ waitFor );
326
+ curl_setopt ($ ch , \CURLOPT_FORBID_REUSE , true );
327
+
328
+ if (0 === curl_multi_add_handle ($ mh , $ ch )) {
329
+ continue ;
330
+ }
331
+ }
325
332
326
- if (\CURLE_RECV_ERROR === $ result && 'H ' === $ waitFor [0 ] && 400 <= ($ responses [(int ) $ ch ]->info ['http_code ' ] ?? 0 )) {
327
- $ multi ->handlesActivity [$ id ][] = new FirstChunk ();
333
+ if (\CURLE_RECV_ERROR === $ result && 'H ' === $ waitFor [0 ] && 400 <= ($ responses [(int ) $ ch ]->info ['http_code ' ] ?? 0 )) {
334
+ $ multi ->handlesActivity [$ id ][] = new FirstChunk ();
335
+ }
336
+
337
+ $ multi ->handlesActivity [$ id ][] = null ;
338
+ $ multi ->handlesActivity [$ id ][] = \in_array ($ result , [\CURLE_OK , \CURLE_TOO_MANY_REDIRECTS ], true ) || '_0 ' === $ waitFor || curl_getinfo ($ ch , \CURLINFO_SIZE_DOWNLOAD ) === curl_getinfo ($ ch , \CURLINFO_CONTENT_LENGTH_DOWNLOAD ) ? null : new TransportException (sprintf ('%s for "%s". ' , curl_strerror ($ result ), curl_getinfo ($ ch , \CURLINFO_EFFECTIVE_URL )));
328
339
}
329
340
330
- $ multi ->handlesActivity [$ id ][] = null ;
331
- $ multi ->handlesActivity [$ id ][] = \in_array ($ result , [\CURLE_OK , \CURLE_TOO_MANY_REDIRECTS ], true ) || '_0 ' === $ waitFor || curl_getinfo ($ ch , \CURLINFO_SIZE_DOWNLOAD ) === curl_getinfo ($ ch , \CURLINFO_CONTENT_LENGTH_DOWNLOAD ) ? null : new TransportException (sprintf ('%s for "%s". ' , curl_strerror ($ result ), curl_getinfo ($ ch , \CURLINFO_EFFECTIVE_URL )));
341
+ if (!$ active && 0 < $ i ) {
342
+ curl_multi_close ($ mh );
343
+ unset($ multi ->handles [$ i ]);
344
+ }
332
345
}
333
346
} finally {
334
347
self ::$ performing = false ;
@@ -358,11 +371,11 @@ private static function select(ClientState $multi, float $timeout): int
358
371
359
372
unset($ multi ->pauseExpiries [$ id ]);
360
373
curl_pause ($ multi ->openHandles [$ id ][0 ], \CURLPAUSE_CONT );
361
- curl_multi_add_handle ($ multi ->handle , $ multi ->openHandles [$ id ][0 ]);
374
+ curl_multi_add_handle ($ multi ->handles [ 0 ] , $ multi ->openHandles [$ id ][0 ]);
362
375
}
363
376
}
364
377
365
- if (0 !== $ selected = curl_multi_select ($ multi ->handle , $ timeout )) {
378
+ if (0 !== $ selected = curl_multi_select ($ multi ->handles [ array_key_last ( $ multi -> handles )] , $ timeout )) {
366
379
return $ selected ;
367
380
}
368
381
@@ -385,15 +398,8 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
385
398
}
386
399
387
400
if ('' !== $ data ) {
388
- try {
389
- // Regular header line: add it to the list
390
- self ::addResponseHeaders ([$ data ], $ info , $ headers );
391
- } catch (TransportException $ e ) {
392
- $ multi ->handlesActivity [$ id ][] = null ;
393
- $ multi ->handlesActivity [$ id ][] = $ e ;
394
-
395
- return \strlen ($ data );
396
- }
401
+ // Regular header line: add it to the list
402
+ self ::addResponseHeaders ([$ data ], $ info , $ headers );
397
403
398
404
if (!str_starts_with ($ data , 'HTTP/ ' )) {
399
405
if (0 === stripos ($ data , 'Location: ' )) {
0 commit comments