{"action":"opened","issue":{"url":"https://api.github.com/repos/bugsnag/bugsnag-php/issues/405","repository_url":"https://api.github.com/repos/bugsnag/bugsnag-php","labels_url":"https://api.github.com/repos/bugsnag/bugsnag-php/issues/405/labels{/name}","comments_url":"https://api.github.com/repos/bugsnag/bugsnag-php/issues/405/comments","events_url":"https://api.github.com/repos/bugsnag/bugsnag-php/issues/405/events","html_url":"https://github.com/bugsnag/bugsnag-php/issues/405","id":256893932,"number":405,"title":"RequestSession callback doesn't cope with exceptions thrown from session handler","user":{"login":"dominics","id":97427,"avatar_url":"https://avatars0.githubusercontent.com/u/97427?v=4","gravatar_id":"","url":"https://api.github.com/users/dominics","html_url":"https://github.com/dominics","followers_url":"https://api.github.com/users/dominics/followers","following_url":"https://api.github.com/users/dominics/following{/other_user}","gists_url":"https://api.github.com/users/dominics/gists{/gist_id}","starred_url":"https://api.github.com/users/dominics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dominics/subscriptions","organizations_url":"https://api.github.com/users/dominics/orgs","repos_url":"https://api.github.com/users/dominics/repos","events_url":"https://api.github.com/users/dominics/events{/privacy}","received_events_url":"https://api.github.com/users/dominics/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-09-12T02:02:36Z","updated_at":"2017-09-12T02:02:36Z","closed_at":null,"author_association":"NONE","body":"Using Silex as an example below, just because that's what I was using to verify the behavior. Context is that yesterday I deployed a buggy session handler that in some circumstances threw an exception (PDOException specifically).\r\n\r\n### Expected behavior\r\n\r\nThis is the basic set up that is working as expected:\r\n\r\n```php\r\n$app = new Silex\\Application();\r\n\r\n$app->register(new \\Silex\\Provider\\SessionServiceProvider());\r\n$app->register(new \\Bugsnag\\Silex\\Silex2ServiceProvider(), [\r\n    'bugsnag.options' => [\r\n        'api_key' => 'deadbeef',\r\n    ]\r\n]);\r\n\r\n$app->error(function (\\Exception $e) use ($app) {\r\n    $app['bugsnag']->notifyException($e);\r\n});\r\n\r\n$app->get('/', function () {\r\n    throw new \\RuntimeException('Some error happened in the controller');\r\n});\r\n\r\nreturn $app;\r\n```\r\n\r\nIn this case, the exception in the controller is correctly reported. However, with the additional of a buggy session handler:\r\n\r\n```php\r\n$app['session.storage.handler'] = function () {\r\n    return new class extends SessionHandler {\r\n        public function open($save_path, $session_name)\r\n        {\r\n            throw new \\RuntimeException('Some error happened in the session handler');\r\n        }\r\n    };\r\n};\r\n```\r\n\r\nNow, we get no exception reported at all (neither of the two thrown exceptions makes it to Bugsnag).\r\n\r\n### Observed behavior\r\n\r\nNo exception in Bugsnag, but the stack trace is:\r\n\r\n```\r\nFatal error:  session_start(): Failed to initialize storage module: user (path: ) in /proj/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php on line 144\r\nStack trace:\r\n  1. {main}() /proj/web/index.php:0\r\n  2. Silex\\Application->run() /proj/web/index.php:10\r\n  3. Silex\\Application->handle() /proj/vendor/silex/silex/src/Silex/Application.php:477\r\n  4. Symfony\\Component\\HttpKernel\\HttpKernel->handle() /proj/vendor/silex/silex/src/Silex/Application.php:496\r\n  5. Symfony\\Component\\HttpKernel\\HttpKernel->handleException() /proj/vendor/symfony/http-kernel/HttpKernel.php:79\r\n  6. Symfony\\Component\\EventDispatcher\\EventDispatcher->dispatch() /proj/vendor/symfony/http-kernel/HttpKernel.php:230\r\n  7. Symfony\\Component\\EventDispatcher\\EventDispatcher->doDispatch() /proj/vendor/symfony/event-dispatcher/EventDispatcher.php:44\r\n  8. call_user_func:{/proj/vendor/symfony/event-dispatcher/EventDispatcher.php:212}() /proj/vendor/symfony/event-dispatcher/EventDispatcher.php:212\r\n  9. Silex\\ExceptionListenerWrapper->__invoke() /proj/vendor/symfony/event-dispatcher/EventDispatcher.php:212\r\n 10. call_user_func:{/proj/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php:53}() /proj/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php:53\r\n 11. {closure:/proj/src/app.php:12-14}() /proj/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php:53\r\n 12. Bugsnag\\Client->notifyException() /proj/src/app.php:13\r\n 13. Bugsnag\\Client->notify() /proj/vendor/bugsnag/bugsnag/src/Client.php:239\r\n 14. Bugsnag\\Pipeline->execute() /proj/vendor/bugsnag/bugsnag/src/Client.php:278\r\n 15. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:56}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:56\r\n 16. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:56\r\n 17. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 18. Bugsnag\\Middleware\\NotificationSkipper->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 19. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Middleware/NotificationSkipper.php:43\r\n 20. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 21. Bugsnag\\Middleware\\BreadcrumbData->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 22. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Middleware/BreadcrumbData.php:43\r\n 23. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 24. Bugsnag\\Middleware\\CallbackBridge->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 25. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Middleware/CallbackBridge.php:41\r\n 26. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 27. Bugsnag\\Middleware\\CallbackBridge->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 28. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Middleware/CallbackBridge.php:41\r\n 29. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 30. Bugsnag\\Middleware\\CallbackBridge->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 31. Bugsnag\\Pipeline->Bugsnag\\{closure}() /proj/vendor/bugsnag/bugsnag/src/Middleware/CallbackBridge.php:41\r\n 32. call_user_func:{/proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68}() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 33. Bugsnag\\Middleware\\CallbackBridge->__invoke() /proj/vendor/bugsnag/bugsnag/src/Pipeline.php:68\r\n 34. Bugsnag\\Callbacks\\RequestSession->__invoke() /proj/vendor/bugsnag/bugsnag/src/Middleware/CallbackBridge.php:40\r\n 35. Bugsnag\\Silex\\Request\\SilexRequest->getSession() /proj/vendor/bugsnag/bugsnag/src/Callbacks/RequestSession.php:38\r\n 36. Symfony\\Component\\HttpFoundation\\Session\\Session->all() /proj/vendor/bugsnag/bugsnag-silex/src/Request/SilexRequest.php:48\r\n 37. Symfony\\Component\\HttpFoundation\\Session\\Session->getAttributeBag() /proj/vendor/symfony/http-foundation/Session/Session.php:103\r\n 38. Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage->getBag() /proj/vendor/symfony/http-foundation/Session/Session.php:259\r\n 39. Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage->start() /proj/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:282\r\n 40. session_start() /proj/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:144\r\n```\r\n\r\nThis example also illustrates something annoying about this bug: nothing in the rest of the app accessed the session until Bugsnag did. That means if you're not using the session elsewhere (and you have a buggy handler), Bugsnag can turn a non-fatal `->notifyException()` into a further exception (usually uncaught and fatal because you're already in an exception handler when you notify).\r\n\r\nTo fix, probably either `Bugsnag\\Request\\RequestInterface`'s `getSession()` implementations would need to handle exceptions, or the `Bugsnag\\Callbacks\\RequestSession`'s `__invoke()` implementation would need to.\r\n\r\n### Version\r\n\r\n3.6.0"}}
{"actor":{"display_login":"dominics"}}