Adds all thread states.

This commit is contained in:
Alliballibaba
2025-09-04 21:28:48 +02:00
parent 0aa4ac1226
commit d13dbe786f
4 changed files with 34 additions and 22 deletions

View File

@@ -2,9 +2,6 @@ package frankenphp
// #include "frankenphp.h"
import "C"
import (
"unsafe"
)
// EXPERIMENTAL: ThreadDebugState prints the state of a single PHP thread - debugging purposes only
type ThreadDebugState struct {
@@ -54,21 +51,33 @@ func threadDebugState(thread *phpThread) ThreadDebugState {
// EXPERIMENTAL: Expose the current thread's information to PHP
//
//export go_frankenphp_info
func go_frankenphp_info(threadIndex C.uintptr_t) unsafe.Pointer {
thread := phpThreads[threadIndex]
func go_frankenphp_info(threadIndex C.uintptr_t) *C.zval {
currentThread := phpThreads[threadIndex]
_, isWorker := currentThread.handler.(*workerThread)
_, isWorker := thread.handler.(*workerThread)
threadInfos := make([]any, 0, len(phpThreads))
for _, thread := range phpThreads {
if thread.state.is(stateReserved) {
continue
}
threadInfos = append(threadInfos, map[string]any{
"index": thread.threadIndex,
"name": thread.name(),
"state": thread.state.name(),
"is_waiting": thread.state.isInWaitingState(),
"waiting_since_milliseconds": thread.state.waitTime(),
})
}
return PHPArray(&Array{
keys: []PHPKey{
PHPKey{Type: PHPStringKey, Str: "thread_name"},
PHPKey{Type: PHPStringKey, Str: "thread_index"},
PHPKey{Type: PHPStringKey, Str: "is_worker_thread"},
},
values: []interface{}{
thread.name(),
int(threadIndex),
isWorker,
},
})
zval := (*C.zval)(PHPMap(map[string]any{
"frankenphp_version": C.GoString(C.frankenphp_get_version().frankenphp_version),
"current_thread": int64(threadIndex),
"is_worker_thread": isWorker,
"threads": threadInfos,
}))
// TODO: how to circumvent pinning?
currentThread.Pin(zval)
return zval
}

View File

@@ -46,6 +46,7 @@ frankenphp_version frankenphp_get_version() {
return (frankenphp_version){
PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION,
PHP_EXTRA_VERSION, PHP_VERSION, PHP_VERSION_ID,
TOSTRING(FRANKENPHP_VERSION)
};
}
@@ -1204,6 +1205,7 @@ PHP_FUNCTION(frankenphp_info) {
RETURN_THROWS();
}
zend_array *result = go_frankenphp_info(thread_index);
RETURN_ARR(result);
zval *result = go_frankenphp_info(thread_index);
RETURN_ARR(Z_ARR_P(result));
}

View File

@@ -36,6 +36,7 @@ typedef struct frankenphp_version {
const char *extra_version;
const char *version;
unsigned long version_id;
const char *frankenphp_version;
} frankenphp_version;
frankenphp_version frankenphp_get_version();

View File

@@ -970,14 +970,14 @@ func TestFileStreamInWorkerMode(t *testing.T) {
func TestFrankenPHPInfo_module(t *testing.T) {
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
body := fetchBody("GET", "http://example.com/frankenphp_info.php", handler)
body, _ := testGet("http://example.com/frankenphp_info.php", handler, t)
assert.Contains(t, body, "[is_worker_thread] => 1")
}, &testOptions{workerScript: "frankenphp_info.php"})
}
func TestFrankenPHPInfo_worker(t *testing.T) {
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
body := fetchBody("GET", "http://example.com/frankenphp_info.php", handler)
body, _ := testGet("http://example.com/frankenphp_info.php", handler, t)
assert.Contains(t, body, "[is_worker_thread] => \n")
}, &testOptions{})
}