fix: catch Throwable in fork child, protect class_exists in scanning

This commit is contained in:
Fabian @ Blax Software 2026-04-16 09:24:11 +02:00
parent 9e7c2575f6
commit ed371ac051
3 changed files with 16 additions and 4 deletions

View File

@ -512,7 +512,12 @@ class Controller
if (isset($seen[$fullClass])) continue; if (isset($seen[$fullClass])) continue;
$seen[$fullClass] = true; $seen[$fullClass] = true;
try {
if (! class_exists($fullClass, true)) continue; if (! class_exists($fullClass, true)) continue;
} catch (\Throwable $e) {
// Class redeclaration or autoload error (e.g. namespace mismatch) — skip
continue;
}
if (! is_subclass_of($fullClass, self::class)) continue; if (! is_subclass_of($fullClass, self::class)) continue;
// Derive event prefix from class name // Derive event prefix from class name

View File

@ -317,7 +317,14 @@ class ControllerResolver
$fullClass = $namespace . $subNamespace . $fileName; $fullClass = $namespace . $subNamespace . $fileName;
// Verify the class exists (triggers autoload) // Verify the class exists (triggers autoload)
if (class_exists($fullClass, true)) { // Wrapped in try-catch: if a file's namespace doesn't match
// its path, autoloading can trigger a class redeclaration error.
try {
$exists = class_exists($fullClass, true);
} catch (\Throwable $e) {
continue;
}
if ($exists) {
// Store with lowercase key for case-insensitive lookup // Store with lowercase key for case-insensitive lookup
$key = strtolower($fileName); $key = strtolower($fileName);
self::$availableControllers[$key] = $fullClass; self::$availableControllers[$key] = $fullClass;

View File

@ -632,7 +632,7 @@ class Handler implements MessageComponentInterface
// Persist session changes to Redis before exit // Persist session changes to Redis before exit
$session->save(); $session->save();
} catch (Exception $e) { } catch (\Throwable $e) {
// Send error via socket pair // Send error via socket pair
$ipc->sendToParent(json_encode([ $ipc->sendToParent(json_encode([
'event' => $message['event'] . ':error', 'event' => $message['event'] . ':error',
@ -640,7 +640,7 @@ class Handler implements MessageComponentInterface
])); ]));
// Log DB connection failures specifically for monitoring // Log DB connection failures specifically for monitoring
if ($this->isDbConnectionError($e)) { if ($e instanceof Exception && $this->isDbConnectionError($e)) {
Log::channel('websocket')->error('DB connection failure in child process', [ Log::channel('websocket')->error('DB connection failure in child process', [
'error' => $e->getMessage(), 'error' => $e->getMessage(),
'event' => $message['event'] ?? 'unknown', 'event' => $message['event'] ?? 'unknown',