Closed (fixed)
Project:
Drupal core
Version:
11.x-dev
Component:
base system
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
19 Jul 2015 at 20:55 UTC
Updated:
6 Jan 2024 at 14:19 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
znerol commentedComment #2
dawehnerGreat observation! I doubt that we should protect the session subsystem, because when this particular DB write fails, other reads might fail as well for example.
It seems to be that this try catch is inherited from D7: https://api.drupal.org/api/drupal/includes%21session.inc/function/_drupa...
Comment #3
alexpottI'm not sure about this because it looks like we're trying to obey PHP's session hander interface...
Comment #4
znerol commentedI was also had concerns about that but after looking at the session code in PHP I think the return value is rather irrelevant. In fact what happens is that if the session handler returns failure and no exception was thrown, then the following PHP warning is emitted: session_write_close(): Failed to write session data (user). Please verify that the current setting of session.save_path is correct (/var/lib/php5). Execution continues after that.
First, for debugging purposes the warning is clearly less useful than an exception because it does not point to the underlying reason. Second, if that db query fails, then the site most likely has much more serious issues than just not being able to save session data. Therefore I think it is reasonable to fail hard in this case.
In addition I reviewed some other session handler implementations (especially from Symfony) and none of them cares to catches exceptions inside the session handler.
Comment #6
mile23The patch from #1 miraculously still applies to 8.1.x.
Re-uploading it here for the testbot. Note that this is @znerol's work and not mine.
Comment #9
dawehnerThis is a really nice improvement IMHO. On the other hand I'm wondering, was the php7 failure a random one?
On top of that I'm wondering whether someone actually tried this out, so drop the database table and see what happens. Does maybe the logging system maybe rely on some session stuff?
Comment #10
anish.a commentedThis patch applies at 8.3.x too. Bumping up the version.
Comment #11
dawehner@anish.a
If a patch still applied there is no reason to reupload it :) Just trigger the retesting and be done with it.
One thing we maybe could do to reduce the maybe potential risk of this patch is to move the exception handler registration further up in
\Drupal\Core\DrupalKernel::bootEnvironmentbasically to the top. The earlier, especially before the test setup, the better.Comment #16
volegerComment #20
jungleAfter removal, it always returns TRUE, looking at the code from the patch in #10, the database operation can go wrong, which may throw an exception and return FALSE accordingly. So proposing the following, then the all possible return values -- TRUE/FALSE of SessionHandlerInterface::write() get respected:
(Rerolled the patch for 9.1.x, meanwhile, made the change proposed, no interdiff)
Comment #21
jungleUse IoC, not sure if we need a BC layer. so used a placeholder CR URL in @trigger_error in the attached patch.
Comment #22
quietone commentedI reviewed the patch and found one nit although I can't comment on the validity of what this patch is doing. Also, does this need a test?
Needs a 'null' added, \Drupal\Component\Datetime\TimeInterface|null
Comment #23
jungleThanks @quietone! Nice catch, tagging "Needs tests".
Comment #24
andypost__NAMESPACE__ . '\SessionHandler::__construct()could use__METHOD__insteadComment #27
rishi.kulshreshthaThis includes the suggestions mentioned above, this still needs a testcase.
Comment #28
andypostshould be 9.3.0 and
will be requiredneeds change tois requiredComment #29
alexpottRe #21 and the change for REQUEST_TIME. That's not in scope here. This issue is about removing the try / catch and not about replacing REQUEST_TIME.
Also the change to catch the exception and return FALSE and then remove all logging is not correct - that will eat the errors even more than HEAD. An exception is not a return value it's an unrecoverable error - returning FALSE at this point does not matter - we expect this to fail. FALSE will mean the system soldiers on but we've failed.
Comment #30
alexpottOne thing that is interesting is that if this returns FALSE then PHP will write to the log... see https://github.com/cakephp/cakephp/issues/13581 for a very similar discussion for another CMS.
Not sure what the correct thing to do here is. It'd be good to add a test to see what happens if the sessions table is dropped mid request and we try to write to it.
Comment #35
znerol commentedRerolling #1 for 11.x. #6 and #10 are identical. Changes introduced in #20 and #21 are not desirable. We do not want to eat the exception if the database write failed. Instead the request should crash hard.
This is inline with session handlers in other projects. E.g., the PdoSessionHandler in symfony explicitly rethrows any exception encountered during db writes.
Comment #36
znerol commentedOpened #3377256: Correctly implement SessionHandlerInterface for other changes (e.g., the
REQUEST_TIMEdeprecation and changed method signatures). Also added credits for @jungle over there.Comment #37
znerol commentedComment #38
smustgrave commentedWas previously tagged for a test which still needs to happen I believe.
Will add related issue to my review list.
Comment #39
znerol commentedRe testing: This class gets installed into the PHP runtime via session_set_save_handler(). Given that fact, I'd argue that the only way to meaningfully cover this is using an end-to-end test.
Good news is that we have functional tests in place for session manager and co. in:
Drupal\Tests\system\Functional\Session\SessionTest.php. No need to add special coverage for the refactoring here IMHO.Comment #40
znerol commentedOk, took me some time to come up this idea for a test:
SessionTestController::triggerWriteExceptionreplaces thesessionstable with an incomplete one in order to trigger an exception duringSessionHandler::write(). So we can look for that from withinSessionTest::testSessionWriteError().Comment #41
znerol commentedAlso switched to MR workflow.
Comment #43
smustgrave commentedSeems to have a test failure.
Comment #44
znerol commentedAh right! The SQL error messages are db specific. Thus, let's look for
DatabaseExceptionWrapper(wraps db specific exceptions) and also the stringINSERT INTOwhich should be present in the error messages generated by all supported databases.Comment #45
smustgrave commentedPerfect LGTM
Comment #47
catchTest coverage looks good. Read back through the discussion and just removing the try/catch seems right here, anything else can happen in other issues. Committed ba5d338 and pushed to 11.x. Thanks!