Files
wordpress-docker/shared/php-fpm/force-debug.php
Elijah Duffy 072c284ba5
All checks were successful
php-fpm-build / build (7.4) (push) Successful in 4m53s
php-fpm: capture & logs exceptions
2025-12-08 20:08:07 -08:00

81 lines
2.4 KiB
PHP

<?php
// force-debug.php
// Automatically prepended; guarantees fatals reach container logs and optionally surfaces verbose output.
$forceDebugRaw = getenv('FORCE_DEBUG_ERRORS');
$forceDebugEnabled = false;
if ($forceDebugRaw !== false) {
$normalized = strtolower(trim($forceDebugRaw));
$forceDebugEnabled = in_array($normalized, ['1', 'true', 'yes', 'on'], true);
}
// Ensure PHP always logs to stderr even if application code tampers with settings.
ini_set('log_errors', '1');
ini_set('error_log', '/proc/self/fd/2');
// Helper to safely write to container stderr without relying on php.ini.
$forceDebugLog = static function (string $message): void {
static $stderr = null;
if ($stderr === null) {
$stderr = @fopen('php://stderr', 'ab');
}
if ($stderr) {
@fwrite($stderr, $message . PHP_EOL);
} else {
// Fallback to PHP's error_log if stderr is unavailable for any reason.
error_log($message);
}
};
// Capture uncaught exceptions so they can never disappear silently.
set_exception_handler(static function (Throwable $throwable) use ($forceDebugLog, $forceDebugEnabled): void {
$message = sprintf(
'[force-debug] Uncaught %s: %s in %s:%d',
get_class($throwable),
$throwable->getMessage(),
$throwable->getFile(),
$throwable->getLine()
);
$forceDebugLog($message);
$forceDebugLog($throwable->getTraceAsString());
if ($forceDebugEnabled) {
http_response_code(500);
echo '<pre>' . htmlspecialchars($message . "\n" . $throwable->getTraceAsString(), ENT_QUOTES, 'UTF-8') . '</pre>';
}
});
// Capture fatal shutdown errors (E_ERROR, E_PARSE, etc.) and surface them to stderr.
register_shutdown_function(static function () use ($forceDebugLog, $forceDebugEnabled): void {
$error = error_get_last();
if ($error === null) {
return;
}
$fatalTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR];
if (!in_array($error['type'], $fatalTypes, true)) {
return;
}
$message = sprintf(
'[force-debug] Fatal error (%s): %s in %s:%d',
$error['type'],
$error['message'],
$error['file'],
$error['line']
);
$forceDebugLog($message);
if ($forceDebugEnabled) {
http_response_code(500);
echo '<pre>' . htmlspecialchars($message, ENT_QUOTES, 'UTF-8') . '</pre>';
}
});
if ($forceDebugEnabled) {
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
$forceDebugLog('[force-debug] Verbose error reporting enabled via FORCE_DEBUG_ERRORS');
}