diff --git a/frankenphp.c b/frankenphp.c index 2c0e6c9..1a72037 100644 --- a/frankenphp.c +++ b/frankenphp.c @@ -558,9 +558,8 @@ static void *manager_thread(void *arg) { free(arg); uintptr_t rh; - while ((rh = go_fetch_request())) { + while ((rh = go_fetch_request())) thpool_add_work(thpool, go_execute_script, (void *) rh); - } /* channel closed, shutdown gracefully */ thpool_wait(thpool); diff --git a/frankenphp.go b/frankenphp.go index 2ca0422..8c87578 100644 --- a/frankenphp.go +++ b/frankenphp.go @@ -5,8 +5,9 @@ // [FrankenPHP app server]: https://frankenphp.dev package frankenphp +//go:generate rm -Rf C-Thread-Pool/ //go:generate git clone --branch=feat/mac-os-compat --depth=1 git@github.com:dunglas/C-Thread-Pool.git -//go:generate rm -rf C-Thread-Pool/.git C-Thread-Pool/.circleci C-Thread-Pool/docs C-Thread-Pool/tests +//go:generate rm -Rf C-Thread-Pool/.git C-Thread-Pool/.circleci C-Thread-Pool/docs C-Thread-Pool/tests // #cgo CFLAGS: -Wall // #cgo CFLAGS: -I/usr/local/include/php -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/main @@ -45,6 +46,7 @@ var ( AlreaydStartedError = errors.New("FrankenPHP is already started") InvalidPHPVersionError = errors.New("FrankenPHP is only compatible with PHP 8.2+") ZendSignalsError = errors.New("Zend Signals are enabled, recompile PHP with --disable-zend-signals") + NotEnoughThreads = errors.New("the number of threads must be superior to the number of workers") MainThreadCreationError = errors.New("error creating the main thread") RequestContextCreationError = errors.New("error during request context creation") RequestStartupError = errors.New("error during PHP request startup") @@ -221,16 +223,18 @@ func Init(options ...Option) error { opt.workers[i].num = numCPU } - numWorkers += w.num + numWorkers += opt.workers[i].num } if opt.numThreads <= 0 { if numWorkers >= numCPU { - // Keep a free thread to handle requests not handled by a worker - opt.numThreads = numCPU + 1 + // Start at least as many threads as workers, and keep a free thread to handle requests in non-worker mode + opt.numThreads = numWorkers + 1 } else { opt.numThreads = numCPU } + } else if opt.numThreads <= numWorkers { + return NotEnoughThreads } switch C.frankenphp_check_version() { diff --git a/frankenphp_test.go b/frankenphp_test.go index 67b3bcf..f07d506 100644 --- a/frankenphp_test.go +++ b/frankenphp_test.go @@ -39,9 +39,6 @@ func runTest(t *testing.T, test func(func(http.ResponseWriter, *http.Request), * if opts == nil { opts = &testOptions{} } - if opts.nbWorkers == 0 { - opts.nbWorkers = 2 - } if opts.nbParrallelRequests == 0 { opts.nbParrallelRequests = 100 } diff --git a/testdata/Caddyfile b/testdata/Caddyfile index fe72ff6..9bbf4bc 100644 --- a/testdata/Caddyfile +++ b/testdata/Caddyfile @@ -1,7 +1,7 @@ { debug frankenphp { - #worker ./phpinfo.php + worker ./phpinfo.php } } diff --git a/worker_test.go b/worker_test.go index 4a0ee6d..d22ee30 100644 --- a/worker_test.go +++ b/worker_test.go @@ -49,6 +49,19 @@ func TestWorkerDie(t *testing.T) { }, &testOptions{workerScript: "die.php", nbWorkers: 1, nbParrallelRequests: 10}) } +func TestNonWorkerModeAlwaysWorks(t *testing.T) { + runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) { + req := httptest.NewRequest("GET", "http://example.com/index.php", nil) + w := httptest.NewRecorder() + handler(w, req) + + resp := w.Result() + body, _ := io.ReadAll(resp.Body) + + assert.Contains(t, string(body), "I am by birth a Genevese") + }, &testOptions{workerScript: "phpinfo.php"}) +} + func ExampleServeHTTP_workers() { if err := frankenphp.Init( frankenphp.WithWorkers("worker1.php", 4),