WritableResourceStream::handleWrite() enters infinite loop on broken TLS socket (EPIPE without PHP warning)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 76/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Tranquilo
- Stack tecnológico
- php
- Área
- backend, networking
Línea de trabajo
Comienza en el guard de handleWrite() alrededor de la línea 151 en src/WritableResourceStream.php y sigue cómo los resultados de fwrite() y las advertencias capturadas afectan al búfer de escritura y al listener. Reproduce el problema con un ReactPHP SecureServer y un cliente TLS terminado abruptamente mientras hay escrituras en cola. Se considera terminado cuando una escritura que devuelve false silenciosamente cierra el stream, mientras que una escritura con valor cero conserva el comportamiento existente dependiente de las advertencias y ya no provoca un bucle de CPU.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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.
- Lenguaje dominante
- PHP
- Estrellas
- 692
- Forks
- 63
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de reactphp/stream
-
Roadmap to reactphp/stream v3 Abiertomaintenance
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
Todos los issues de reactphp/stream
Issues similares
-
sync-en
Dificultad 1/5 1-3 horas Aptitud para principiantes 85/100
-
sync-en
Dificultad 1/5 1-3 horas Aptitud para principiantes 85/100
-
Перевод устарел
Dificultad 1/5 1-3 horas Aptitud para principiantes 78/100
-
[6.x]: "Cannot use object of type stdClass as array" loading Users index (regression of #19182) Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 90/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100