WritableResourceStream::handleWrite() enters infinite loop on broken TLS socket (EPIPE without PHP warning)
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 76/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Ruhig
- Tech-Stack
- php
- Bereich
- backend, networking
Rechercherichtung
Beginnen Sie in src/WritableResourceStream.php beim handleWrite()-Guard um Zeile 151 und verfolgen Sie dann, wie sich die Ergebnisse von fwrite() und abgefangene Warnungen auf den Schreibpuffer und den Listener auswirken. Reproduzieren Sie das Problem mit einem ReactPHP SecureServer und einem abrupt beendeten TLS-Client, während Schreibvorgänge in der Warteschlange stehen. Als abgeschlossen gilt die Änderung, wenn ein stilles false beim Schreiben den Stream schließt, während ein Schreiben mit dem Ergebnis null das bestehende warnungsabhängige Verhalten beibehält und keine CPU-Schleife mehr verursacht.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
On PHP 8.x with react/socket's SecureServer (TLS), when a remote client disconnects abruptly, epoll reports EPOLLOUT|EPOLLHUP on the dead socket FD. WritableResourceStream::handleWrite() calls fwrite(), which returns false because the kernel write() returns -1 EPIPE. However, PHP's OpenSSL stream wrapper does not call php_error_docref() for SSL_ERROR_SYSCALL+EPIPE errors in all code paths. The set_error_handler capture therefore gets nothing ($error === null).
The guard evaluates to false, so close() is never called. WritableResourceStream then silently passes false to substr() (implicit cast to 0 in non-strict mode), leaving the write buffer unchanged and the write listener active. epoll keeps returning EPOLLOUT|EPOLLHUP, fwrite() keeps returning false silently - 100% CPU lockup.
Reproduction: use react/socket SecureServer with TLS, kill a client with kill -9 while the server has queued writes to that client.
Fix: separate the $sent === false case (hard error - always close) from $sent === 0 (may be transient EAGAIN/WANT_WRITE - only close when PHP warning is present):
// Before
if (($sent === 0 || $sent === false) && $error !== null) {
// After
if ($sent === false || ($sent === 0 && $error !== null)) {
This issue was investigated with the help of AI, but the 100% CPU usage issue is real and after applying the above fix on production, it seems to have disappeared.
- Vorherrschende Sprache
- PHP
- Sterne
- 692
- Forks
- 63
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus reactphp/stream
-
maintenance
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 20/100
Alle Issues in reactphp/stream
Ähnliche Issues
-
sync-en
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 85/100
-
sync-en
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 85/100
-
Перевод устарел
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 78/100
-
[6.x]: "Cannot use object of type stdClass as array" loading Users index (regression of #19182) Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 90/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100