Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions docs/worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ The following example shows how to create your own worker script without relying
<?php
// public/index.php

// Prevent worker script termination when a client connection is interrupted
ignore_user_abort(true);

// Boot your app
require __DIR__.'/vendor/autoload.php';

Expand Down
6 changes: 6 additions & 0 deletions frankenphp.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ frankenphp_config frankenphp_get_config() {
}

bool should_filter_var = 0;
bool original_user_abort_setting = 0;

__thread uintptr_t thread_index;
__thread bool is_worker_thread = false;
__thread zval *os_environment = NULL;
Expand Down Expand Up @@ -113,6 +115,9 @@ __thread session_user_handlers *worker_session_handlers_snapshot = NULL;

void frankenphp_update_local_thread_context(bool is_worker) {
is_worker_thread = is_worker;

/* workers should keep running if the user aborts the connection */
PG(ignore_user_abort) = is_worker ? 1 : original_user_abort_setting;
}

static void frankenphp_update_request_context() {
Expand Down Expand Up @@ -1241,6 +1246,7 @@ static void *php_main(void *arg) {
char *default_filter;
cfg_get_string("filter.default", &default_filter);
should_filter_var = default_filter != NULL;
original_user_abort_setting = PG(ignore_user_abort);

go_frankenphp_main_thread_is_ready();

Expand Down
17 changes: 17 additions & 0 deletions worker_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package frankenphp_test

import (
"context"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -157,3 +158,19 @@ func TestWorkerHasOSEnvironmentVariableInSERVER(t *testing.T) {
assert.Contains(t, string(body), "custom_env_variable_value")
}, &testOptions{workerScript: "worker.php", nbWorkers: 1, nbParallelRequests: 1})
}

func TestKeepRunningOnConnectionAbort(t *testing.T) {
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
req := httptest.NewRequest("GET", "http://example.com/worker-with-counter.php", nil)

ctx, cancel := context.WithCancel(req.Context())
req = req.WithContext(ctx)
cancel()
body1, _ := testRequest(req, handler, t)

assert.Equal(t, "requests:1", body1, "should have handled exactly one request")
body2, _ := testGet("http://example.com/worker-with-counter.php", handler, t)

assert.Equal(t, "requests:2", body2, "should not have stopped execution after the first request was aborted")
}, &testOptions{workerScript: "worker-with-counter.php", nbWorkers: 1, nbParallelRequests: 1})
}