Commit 62ae031
authored
[PHP] Fix "Controller is already closed" crash in CLI server (#3441)
## Summary
This PR fixes two related Node-side crash paths in PHP-WASM that could
bring down the Playground CLI server instead of failing a single request
cleanly.
The first crash happened when PHP had already produced output, which
closes the headers stream, and then execution failed afterwards. In that
case, Node could still try to `error()` a `ReadableStream` controller
that had already been closed, which threw:
```text
TypeError [ERR_INVALID_STATE]: Invalid state: Controller is already closed
```
The validated repro for that path is:
1. PHP writes output
2. `closeHeadersStream()` closes the headers controller
3. a later WASM/runtime error occurs
4. error handling tries to signal the already-closed controller
A simple `echo ...; exit;` by itself is not the exact repro.
The second crash happened when a stream consumer cancelled the response
stream before PHP finished, for example because the HTTP pipeline
completed or the client disconnected. In that case, the runtime could
still try to `close()` an already-cancelled controller and hit the same
`Controller is already closed` failure.
The third crash path was in the `proc_open()` bridge used by the Node
PHP runtime. If a spawned process timed out or exited while Node still
had buffered stdout/stderr chunks to forward, the generated `php.js`
bridge could try to write into a PIPEFS stream that PHP had already
closed. That crashed the host with an error like:
```text
TypeError: Cannot read properties of null (reading 'length')
```
Example:
```php
<?php
$res = proc_open(
"hanging_command",
[
["pipe", "r"],
["pipe", "w"],
["pipe", "w"],
],
$pipes
);
fread($pipes[1], 1024);
```
## What changed
- Added defensive stream-controller handling in the universal runtime
and stream bridge so already-closed controllers no longer crash the host
process.
- Fixed child stdout/stderr teardown in the Emscripten Node bridge by
detaching listeners on exit and ignoring late chunks after PHP has
already closed the child-side pipe.
- Added `off()` to the shared `EventEmitter` interface so the
child-process typing matches the APIs used by the runtime cleanup logic.
- Regenerated all checked-in Node PHP binaries (`asyncify` and `jspi`,
PHP 7.4 through 8.5) from the updated build source.
## Test plan
CI1 parent 66aedcd commit 62ae031
File tree
35 files changed
+144049
-170783
lines changed- packages/php-wasm
- compile/php
- node-builds
- 7-4
- asyncify
- 7_4_33
- jspi
- 7_4_33
- 8-0
- asyncify
- 8_0_30
- jspi
- 8_0_30
- 8-1
- asyncify
- 8_1_34
- jspi
- 8_1_34
- 8-2
- asyncify
- 8_2_30
- jspi
- 8_2_30
- 8-3
- asyncify
- 8_3_30
- jspi
- 8_3_30
- 8-4
- asyncify
- 8_4_19
- jspi
- 8_4_19
- 8-5
- asyncify
- 8_5_4
- jspi
- 8_5_4
- node/src/test
- universal/src/lib
35 files changed
+144049
-170783
lines changedLines changed: 43 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
661 | 661 | | |
662 | 662 | | |
663 | 663 | | |
| 664 | + | |
664 | 665 | | |
665 | 666 | | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
666 | 670 | | |
667 | 671 | | |
668 | 672 | | |
| |||
689 | 693 | | |
690 | 694 | | |
691 | 695 | | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
702 | 717 | | |
703 | 718 | | |
704 | 719 | | |
| |||
707 | 722 | | |
708 | 723 | | |
709 | 724 | | |
710 | | - | |
711 | | - | |
712 | | - | |
713 | | - | |
714 | | - | |
715 | | - | |
716 | | - | |
717 | | - | |
718 | | - | |
719 | | - | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
720 | 743 | | |
721 | 744 | | |
722 | 745 | | |
| |||
Binary file not shown.
0 commit comments