User tests: Successful: Unsuccessful:
This is the vendor neutral fix, I have another pull request open with a preferred mysql specific fix.
A bug exists in JSessionStorageDatabase::write() (libraries/joomla/session/storage/database.php:94). The logic assumes that an update will have one affected row if a session exists. However, this is not true. The timestamp is only granular in seconds and may be the same with multiple ajax requests, refreshes on different tabs, etc. When the timestamp is the same the entry is exactly the same and the update will not affect any rows. With the current logic an insert will be attempted and this results in a 500.
This fix uses a SELECT COUNT to determine a session row currently exists and should be updated.
500 - JDatabaseMySQLi::query: 1062 - Duplicate entry 'e33c3ab2b05a9dc97dc25187a823b8e6' for key 'PRIMARY' SQL=INSERT INTO `jos_session` (`session_id`, `data`, `time`) VALUES ('e33c3ab2b05a9dc97dc25187a823b8e6', '__default|a:8:{s:22:\"session.client.browser\";s:119:\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.54 Safari/535.19\";s:15:\"session.counter\";i:43;s:8:\"registry\";O:9:\"JRegistry\":1:{s:7:\"\0*\0data\";O:8:\"stdClass\":0:{}}s:4:\"user\";O:5:\"JUser\":23:{s:9:\"\0*\0isRoot\";b:0;s:2:\"id\";i:0;s:4:\"name\";N;s:8:\"username\";N;s:5:\"email\";N;s:8:\"password\";N;s:14:\"password_clear\";s:0:\"\";s:8:\"usertype\";N;s:5:\"block\";N;s:9:\"sendEmail\";i:0;s:12:\"registerDate\";N;s:13:\"lastvisitDate\";N;s:10:\"activation\";N;s:6:\"params\";N;s:6:\"groups\";a:0:{}s:5:\"guest\";i:1;s:10:\"\0*\0_params\";O:9:\"JRegistry\":1:{s:7:\"\0*\0data\";O:8:\"stdClass\":0:{}}s:14:\"\0*\0_authGroups\";a:1:{i:0;i:1;}s:14:\"\0*\0_authLevels\";a:2:{i:0;i:1;i:1;i:1;}s:15:\"\0*\0_authActions\";N;s:12:\"\0*\0_errorMsg\";N;s:10:\"\0*\0_errors\";a:0:{}s:3:\"aid\";i:0;}s:13:\"session.token\";s:32:\"cc3f66462deb72a899115b2ea51f8608\";s:19:\"session.timer.start\";i:1331743210;s:18:\"session.timer.last\";i:1331744856;s:17:\"session.timer.now\";i:1331744857;}', '1331744857')
I will be so happy never to have a bug report or forum discussion on that again.
me 2 +1 LOL
see my comment in the tracker about microtime
Those who need to work this around can use something like this:
JFactory::getSession()->set('com_docman.fix.the.session.bug', microtime(true));
@ercanozkaya don't forget to update you session table to be able to contain all the microtime:
ALTER TABLE #__jos_session MODIFY COLUMN time varchar(15) DEFAULT '';
The point everyone misses is this: Using a session in more than one concurrent request requires proper locking. Otherwise, a situation like this destroys data: Two requests both read the session data first, then both change different things in the session, and after a different runtime, both try to save to the storage. The request saving last wins.
This problem is included in ALL Joomla session storage modules with the exception of the "None" module, because neither acquires an exclusive lock on the session data when executing "open()" and releases it when executing "close()".
I'm closing this as it's not mergeable and 2 years old. Feel free to open if you update it and are still interested in get it merged.
Thanks for contributing.
tracker item http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=28249