From 13434b1a18e76cf9c138101bf129dfd63ed55aec Mon Sep 17 00:00:00 2001 From: Markus Fasselt Date: Thu, 26 Jan 2017 17:19:30 +0100 Subject: [PATCH 1/2] Use proper error message when session write fails #20807 --- .../Session/Storage/NativeSessionStorage.php | 24 ++++++++++++++++++- .../Storage/Proxy/SessionHandlerProxy.php | 8 +++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 274b0df6b9e39..1c0240ecd37a2 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -223,7 +223,29 @@ public function regenerate($destroy = false, $lifetime = null) */ public function save() { - session_write_close(); + try { + session_write_close(); + } catch (\ErrorException $e) { + // The default PHP error message is not very helpful, as it does not give any information on the curently + // used save handler. + // Therefore, we catch this exception and throw a new exception is a proper exception message + $handler = $this->getSaveHandler(); + if ($handler instanceof SessionHandlerProxy) { + $handler = $handler->getHandler(); + } + + throw new \ErrorException( + sprintf( + 'session_write_close(): Failed to write session data with %s handler', + get_class($handler) + ), + $e->getCode(), + $e->getSeverity(), + $e->getFile(), + $e->getLine(), + $e + ); + } if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { // This condition matches only PHP 5.3 with internal save handlers diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php index 81643c74b4001..9284f06b3bde8 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -35,6 +35,14 @@ public function __construct(\SessionHandlerInterface $handler) $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; } + /** + * @return \SessionHandlerInterface + */ + public function getHandler(): \SessionHandlerInterface + { + return $this->handler; + } + // \SessionHandlerInterface /** From d37ba311c8d551f5ca88b687e1dbb41e0dc5f703 Mon Sep 17 00:00:00 2001 From: Markus Fasselt Date: Sun, 19 Feb 2017 00:02:51 +0100 Subject: [PATCH 2/2] Improve error handling on failed session write --- .../Session/Storage/NativeSessionStorage.php | 30 +++++++++---------- .../Storage/Proxy/SessionHandlerProxy.php | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 1c0240ecd37a2..6f1f9bef32ede 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -11,6 +11,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; +use Symfony\Component\Debug\Exception\ContextErrorException; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; @@ -223,28 +224,27 @@ public function regenerate($destroy = false, $lifetime = null) */ public function save() { + // Register custom error handler to catch a possible failure warning during session write + set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) { + throw new ContextErrorException($errstr, $errno, E_WARNING, $errfile, $errline, $errcontext); + }, E_WARNING); + try { session_write_close(); - } catch (\ErrorException $e) { - // The default PHP error message is not very helpful, as it does not give any information on the curently - // used save handler. - // Therefore, we catch this exception and throw a new exception is a proper exception message + restore_error_handler(); + } catch (ContextErrorException $e) { + // The default PHP error message is not very helpful, as it does not give any information on the current save handler. + // Therefore, we catch this error and trigger a warning with a better error message $handler = $this->getSaveHandler(); if ($handler instanceof SessionHandlerProxy) { $handler = $handler->getHandler(); } - throw new \ErrorException( - sprintf( - 'session_write_close(): Failed to write session data with %s handler', - get_class($handler) - ), - $e->getCode(), - $e->getSeverity(), - $e->getFile(), - $e->getLine(), - $e - ); + restore_error_handler(); + trigger_error(sprintf( + 'session_write_close(): Failed to write session data with %s handler', + get_class($handler) + ), E_USER_WARNING); } if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php index 9284f06b3bde8..592cfe166f8c7 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -38,7 +38,7 @@ public function __construct(\SessionHandlerInterface $handler) /** * @return \SessionHandlerInterface */ - public function getHandler(): \SessionHandlerInterface + public function getHandler() { return $this->handler; }