@@ -100,9 +100,10 @@ public function handleClient(
100100 $ this ->insertTimeout ();
101101
102102 $ headerSizeLimit = $ this ->headerSizeLimit ;
103+ $ cancellation = $ this ->deferredCancellation ->getCancellation ();
103104
104105 try {
105- $ buffer = $ readableStream ->read ();
106+ $ buffer = $ readableStream ->read ($ cancellation );
106107 if ($ buffer === null ) {
107108 $ this ->removeTimeout ();
108109 return ;
@@ -141,7 +142,7 @@ public function handleClient(
141142 );
142143 }
143144
144- $ chunk = $ readableStream ->read ();
145+ $ chunk = $ readableStream ->read ($ cancellation );
145146 if ($ chunk === null ) {
146147 return ;
147148 }
@@ -413,7 +414,8 @@ public function handleClient(
413414 $ this ->suspendTimeout ();
414415
415416 $ this ->currentBuffer = $ buffer ;
416- $ this ->handleRequest ($ request );
417+ $ this ->pendingResponse = async ($ this ->handleRequest (...), $ request );
418+ $ this ->pendingResponse ->await ();
417419 $ this ->pendingResponseCount --;
418420
419421 continue ;
@@ -486,7 +488,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
486488 );
487489 }
488490
489- $ chunk = $ this ->readableStream ->read ();
491+ $ chunk = $ this ->readableStream ->read ($ cancellation );
490492 if ($ chunk === null ) {
491493 return ;
492494 }
@@ -514,7 +516,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
514516
515517 if ($ chunkLengthRemaining === 0 ) {
516518 while (!isset ($ buffer [1 ])) {
517- $ chunk = $ readableStream ->read ();
519+ $ chunk = $ readableStream ->read ($ cancellation );
518520 if ($ chunk === null ) {
519521 return ;
520522 }
@@ -546,7 +548,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
546548 );
547549 }
548550
549- $ chunk = $ this ->readableStream ->read ();
551+ $ chunk = $ this ->readableStream ->read ($ cancellation );
550552 if ($ chunk === null ) {
551553 return ;
552554 }
@@ -599,7 +601,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
599601 $ remaining -= $ bodyBufferSize ;
600602 }
601603
602- $ body = $ readableStream ->read ();
604+ $ body = $ readableStream ->read ($ cancellation );
603605 if ($ body === null ) {
604606 return ;
605607 }
@@ -635,7 +637,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
635637 $ bufferLength = \strlen ($ buffer );
636638
637639 if (!$ bufferLength ) {
638- $ chunk = $ readableStream ->read ();
640+ $ chunk = $ readableStream ->read ($ cancellation );
639641 if ($ chunk === null ) {
640642 return ;
641643 }
@@ -647,7 +649,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
647649 // These first two (extreme) edge cases prevent errors where the packet boundary ends after
648650 // the \r and before the \n at the end of a chunk.
649651 if ($ bufferLength === $ chunkLengthRemaining || $ bufferLength === $ chunkLengthRemaining + 1 ) {
650- $ chunk = $ readableStream ->read ();
652+ $ chunk = $ readableStream ->read ($ cancellation );
651653 if ($ chunk === null ) {
652654 return ;
653655 }
@@ -704,7 +706,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
704706 $ bodySize += $ bodyBufferSize ;
705707 }
706708
707- $ chunk = $ readableStream ->read ();
709+ $ chunk = $ readableStream ->read ($ cancellation );
708710 if ($ chunk === null ) {
709711 return ;
710712 }
@@ -756,6 +758,12 @@ static function (int $bodySize) use (&$bodySizeLimit): void {
756758 }
757759 } catch (StreamException ) {
758760 // Client disconnected, finally block will clean up.
761+ } catch (CancelledException ) {
762+ // Server shutting down.
763+ if ($ this ->bodyQueue === null || !$ this ->pendingResponseCount ) {
764+ // Send a service unavailable response only if another response has not already been sent.
765+ $ this ->sendServiceUnavailableResponse ($ request ?? null )->await ();
766+ }
759767 } finally {
760768 $ this ->pendingResponse ->finally (function (): void {
761769 $ this ->removeTimeout ();
@@ -1023,6 +1031,19 @@ private function upgrade(Request $request, Response $response): void
10231031 }
10241032 }
10251033
1034+ /**
1035+ * Creates a service unavailable response from the error handler and sends that response to the client.
1036+ *
1037+ * @return Future<void>
1038+ */
1039+ private function sendServiceUnavailableResponse (?Request $ request ): Future
1040+ {
1041+ $ response = $ this ->errorHandler ->handleError (HttpStatus::SERVICE_UNAVAILABLE , request: $ request );
1042+ $ response ->setHeader ("connection " , "close " );
1043+
1044+ return $ this ->lastWrite = async ($ this ->send (...), $ this ->lastWrite , $ response );
1045+ }
1046+
10261047 /**
10271048 * Creates an error response from the error handler and sends that response to the client.
10281049 *
@@ -1062,6 +1083,7 @@ public function stop(): void
10621083
10631084 $ this ->pendingResponse ->await ();
10641085 $ this ->lastWrite ?->await();
1086+ $ this ->deferredCancellation ->cancel ();
10651087 }
10661088
10671089 public function getApplicationLayerProtocols (): array
0 commit comments