@@ -13,7 +13,7 @@ class MultiCurl extends BaseCurl
1313 public $ stopTime = null ;
1414
1515 private $ queuedCurls = [];
16- private $ activeCurls = [] ;
16+ protected \ WeakMap $ activeCurls ;
1717 private $ isStarted = false ;
1818 private $ currentStartTime = null ;
1919 private $ currentRequestCount = 0 ;
@@ -47,6 +47,7 @@ public function __construct($base_url = null)
4747 {
4848 $ this ->multiCurl = curl_multi_init ();
4949 $ this ->headers = new CaseInsensitiveArray ();
50+ $ this ->activeCurls = new \WeakMap ();
5051
5152 if ($ base_url !== null ) {
5253 $ this ->setUrl ($ base_url );
@@ -684,40 +685,40 @@ public function start()
684685 (($ info_array = curl_multi_info_read ($ this ->multiCurl )) !== false )
685686 ) {
686687 if ($ info_array ['msg ' ] === CURLMSG_DONE ) {
687- foreach ($ this ->activeCurls as $ key => $ curl ) {
688- if ($ curl ->curl === $ info_array ['handle ' ]) {
689- // Set the error code for multi handles using the "result" key in the array returned by
690- // curl_multi_info_read(). Using curl_errno() on a multi handle will incorrectly return 0
691- // for errors.
692- $ curl ->curlErrorCode = $ info_array ['result ' ];
693- $ curl ->exec ($ curl ->curl );
694-
695- if ($ curl ->attemptRetry ()) {
696- // Remove completed handle before adding again in order to retry request.
697- curl_multi_remove_handle ($ this ->multiCurl , $ curl ->curl );
698-
699- $ curlm_error_code = curl_multi_add_handle ($ this ->multiCurl , $ curl ->curl );
700- if ($ curlm_error_code !== CURLM_OK ) {
701- throw new \ErrorException (
702- 'cURL multi add handle error: ' . curl_multi_strerror ($ curlm_error_code )
703- );
704- }
705-
706- $ curl ->call ($ curl ->beforeSendCallback );
707- } else {
708- $ curl ->execDone ();
709-
710- // Remove completed instance from active curls.
711- unset($ this ->activeCurls [$ key ]);
712-
713- // Remove handle of the completed instance.
714- curl_multi_remove_handle ($ this ->multiCurl , $ curl ->curl );
715-
716- // Clean up completed instance.
717- $ curl ->close ();
688+ $ native_handle = $ info_array ['handle ' ];
689+
690+ if ($ this ->activeCurls ->offsetExists ($ native_handle )) {
691+ $ curl = $ this ->activeCurls [$ native_handle ];
692+
693+ // Set the error code for multi handles using the "result" key in the array returned by
694+ // curl_multi_info_read(). Using curl_errno() on a multi handle will incorrectly return 0
695+ // for errors.
696+ $ curl ->curlErrorCode = $ info_array ['result ' ];
697+ $ curl ->exec ($ native_handle );
698+
699+ if ($ curl ->attemptRetry ()) {
700+ // Remove completed handle before adding again in order to retry request.
701+ curl_multi_remove_handle ($ this ->multiCurl , $ native_handle );
702+
703+ $ curlm_error_code = curl_multi_add_handle ($ this ->multiCurl , $ native_handle );
704+ if ($ curlm_error_code !== CURLM_OK ) {
705+ throw new \ErrorException (
706+ 'cURL multi add handle error: ' . curl_multi_strerror ($ curlm_error_code )
707+ );
718708 }
719709
720- break ;
710+ $ curl ->call ($ curl ->beforeSendCallback );
711+ } else {
712+ $ curl ->execDone ();
713+
714+ // Remove completed instance from active curls.
715+ $ this ->activeCurls ->offsetUnset ($ native_handle );
716+
717+ // Remove handle of the completed instance.
718+ curl_multi_remove_handle ($ this ->multiCurl , $ native_handle );
719+
720+ // Clean up completed instance.
721+ $ curl ->close ();
721722 }
722723 }
723724 }
@@ -734,22 +735,33 @@ public function start()
734735 #[\Override]
735736 public function stop ()
736737 {
738+ if (!$ this ->isStarted ) {
739+ return ;
740+ }
741+
737742 // Remove any queued curl requests.
738743 while (count ($ this ->queuedCurls )) {
739744 $ curl = array_pop ($ this ->queuedCurls );
740745 $ curl ->close ();
741746 }
742747
748+ /**
749+ * @var \CurlHandle $native_handle
750+ * @var \Curl\Curl $curl
751+ */
743752 // Attempt to stop active curl requests.
744- while (count ($ this ->activeCurls )) {
745- // Remove instance from active curls.
746- $ curl = array_pop ($ this ->activeCurls );
747-
753+ foreach ($ this ->activeCurls as $ native_handle => $ curl ) {
748754 // Remove active curl handle.
749- curl_multi_remove_handle ($ this ->multiCurl , $ curl ->curl );
755+ curl_multi_remove_handle ($ this ->multiCurl , $ native_handle );
756+
757+ // Remove instance from active curls.
758+ $ this ->activeCurls ->offsetUnset ($ native_handle );
750759
751760 $ curl ->stop ();
752761 }
762+
763+ $ this ->isStarted = false ;
764+ $ this ->stopTime = microtime (true );
753765 }
754766
755767 /**
@@ -825,7 +837,7 @@ private function initHandle()
825837
826838 // Add instance to list of active curls.
827839 $ this ->currentRequestCount += 1 ;
828- $ this ->activeCurls [$ curl ->id ] = $ curl ;
840+ $ this ->activeCurls [$ curl ->curl ] = $ curl ;
829841
830842 // Set callbacks if not already individually set.
831843 if ($ curl ->beforeSendCallback === null ) {
0 commit comments