From 7939dbe098f45efbfcf7057fbdd119fd7ec32f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 28 Sep 2023 15:45:18 +0200 Subject: [PATCH] test: prove that Fibers work if not calling Go --- README.md | 1 + docs/known-issues.md | 32 ++++++++++++++++++++++++++++++++ frankenphp_test.go | 17 +++++++++++++++++ testdata/fiber-no-cgo.php | 12 ++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 docs/known-issues.md create mode 100644 testdata/fiber-no-cgo.php diff --git a/README.md b/README.md index b568adbc7..183ce8a9d 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ containing [PHP 8.2](https://www.php.net/releases/8.2/en.php) and most popular P * [Docker images](docs/docker.md) * [Compile from sources](docs/compile.md) * [Create static binaries](docs/static.md) +* [Known issues](docs/known-issues.md) * [Demo app (Symfony) and benchmarks](https://github.com/dunglas/frankenphp-demo) * [Go library documentation](https://pkg.go.dev/github.com/dunglas/frankenphp) * [Contributing and debugging](CONTRIBUTING.md) diff --git a/docs/known-issues.md b/docs/known-issues.md new file mode 100644 index 000000000..0304ed20c --- /dev/null +++ b/docs/known-issues.md @@ -0,0 +1,32 @@ +# Known Issues + +## Fibers + +Calling PHP functions and language constructs that themselves call [cgo](https://go.dev/blog/cgo) in [Fibers](https://www.php.net/manual/en/language.fibers.php) is known to cause crashes. + +This issue [is being worked on by the Go project](https://github.com/golang/go/issues/62130). + + +In the meantime, one solution is not to use constructs (like `echo`) and functions (like `header()`) that delegate to Go from inside Fibers. + +This code will likely crash because it uses `echo` in the Fiber: + +```php +$fiber = new Fiber(function() { + echo 'In the Fiber'.PHP_EOL; + echo 'Still inside'.PHP_EOL; +}); +$fiber->start(); +``` + +Instead, return the value from the Fiber and use it outside: + +```php +$fiber = new Fiber(function() { + Fiber::suspend('In the Fiber'.PHP_EOL)); + Fiber::suspend('Still inside'.PHP_EOL)); +}); +echo $fiber->start(); +echo $fiber->resume(); +$fiber->resume(); +``` diff --git a/frankenphp_test.go b/frankenphp_test.go index 20c47a5a2..eb4b50bb6 100644 --- a/frankenphp_test.go +++ b/frankenphp_test.go @@ -571,3 +571,20 @@ func ExampleServeHTTP() { }) log.Fatal(http.ListenAndServe(":8080", nil)) } + +func TestFiberNoCgo_module(t *testing.T) { testFiberNoCgo(t, &testOptions{}) } +func TestFiberNonCgo_worker(t *testing.T) { + testFiberNoCgo(t, &testOptions{workerScript: "fiber-no-cgo.php"}) +} +func testFiberNoCgo(t *testing.T, opts *testOptions) { + runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) { + req := httptest.NewRequest("GET", fmt.Sprintf("http://example.com/fiber-no-cgo.php?i=%d", i), nil) + w := httptest.NewRecorder() + handler(w, req) + + resp := w.Result() + body, _ := io.ReadAll(resp.Body) + + assert.Equal(t, string(body), fmt.Sprintf("Fiber %d", i)) + }, opts) +} diff --git a/testdata/fiber-no-cgo.php b/testdata/fiber-no-cgo.php new file mode 100644 index 000000000..c2ea5f96c --- /dev/null +++ b/testdata/fiber-no-cgo.php @@ -0,0 +1,12 @@ +start(); + + $fiber->resume(); +}; +