This is resolved and patched in the documentation: https://github.com/cakephp/docs/commit/23fc03c12c3eea8456e895c2696444e037cdcc56
Thanks! /Lionel On Thursday, 12 September 2013 10:23:21 UTC+8, Lionel Chan wrote: > > Hi All > > *Environment:* > CakePHP version: *2.4.0 stable* > latest PHP 5.3 > > We just recently pushed our app to AWS Beanstalk with ElastiCache + RDS as > our combo session, and using the ComboSession technique described in > here<http://book.cakephp.org/2.0/en/development/sessions.html#creating-a-custom-session-handler>. > > At first everything was ok, but then out of sudden, our app keep running > into some infinity loops that we can't really reproduce at that point of > time. What we can do is basically remove the cookie key from RDS, or clear > browser cookie. Clearly it has something to do with Session. > > So these are our sample error_logs: > > [Wed Sep 11 03:56:27 2013] [error] [client 10.251.91.107] PHP Fatal error: > Maximum execution time of 60 seconds exceeded in > /var/app/current/lib/Cake/Model/Datasource/CakeSession.php on line 612 > [Wed Sep 11 04:00:49 2013] [error] [client 10.251.91.107] PHP Fatal error: > Maximum execution time of 60 seconds exceeded in > /var/app/current/lib/Cake/Model/Datasource/CakeSession.php on line 612 > [Wed Sep 11 04:03:02 2013] [error] [client 10.251.91.107] PHP Fatal error: > Maximum execution time of 60 seconds exceeded in > /var/app/current/lib/Cake/Model/Datasource/CakeSession.php on line 612 > .... repeating .... > [Thu Sep 12 01:11:48 2013] [error] [client 10.251.91.107] PHP Fatal error: > Maximum execution time of 60 seconds exceeded in > /var/app/current/lib/Cake/Model/Datasource/CakeSession.php on line 612 > [Thu Sep 12 01:13:50 2013] [error] [client 10.251.91.107] PHP Fatal error: > Maximum execution time of 60 seconds exceeded in > /var/app/current/lib/Cake/Model/Datasource/CakeSession.php on line 612 > [Thu Sep 12 01:15:15 2013] [error] [client 10.251.91.107] PHP Fatal error: > Allowed memory size of 268435456 bytes exhausted (tried to allocate 523800 > bytes) in /var/app/current/lib/Cake/Model/Model.php on line 1368 > > So apparently CakeSession is trying to session_start in a loop that it > can't resolve the session successfully. > > Then we found out one serious issue with the *ComboSession.php* mentioned > in the post > http://book.cakephp.org/2.0/en/development/sessions.html#creating-a-custom-session-handler, > > that, let's say, if Cache lost the session data, and Cache::delete($id) > fails, parent::destroy() will simply won't be called to destroy expired > session. > > That says, we run into this kind of loop: > > *Let's assume Cache lost the session data, and RDS retained a piece of > expired session data:* > 1. CakeSession::start() > 2. CakeSession::_startSession() - session data get loaded from RDS because > Cache::read returns false > 3. CakeSession::_checkValid() > 4. CakeSession::_validAgentAndTime() - obviously timeout, we got an > invalid data here > 5. CakeSession::destroy() - this calls destroy the session and trying to > call session_destroy() > 6. ComboSession::destroy($id) - this calls attempted to destroy the > session data from Cache but failed (Memcache engine says not found!), and > since it's failed, parent::destroy() will never get triggered, and so *old > session data is survived*. > 7. Go to step 1 and continues looping, and PHP will dies either the whole > memory get filled up or time out. > > > To reproduce, we use this modified version of ComboSession to simulate the > problem: *(The following code is to demonstrate the bug, not a working > copy!)* > > <?php > App::uses('DatabaseSession', 'Model/Datasource/Session'); > > class ComboSession extends DatabaseSession implements > CakeSessionHandlerInterface { > public $cacheKey; > > public function __construct() { > $this->cacheKey = Configure::read('Session.handler.cache'); > parent::__construct(); > } > > // read data from the session. > public function read($id) { > $result = false; //simulate cache read fails > if ($result) { > return $result; > } > return parent::read($id); > } > > // write data into the session. > public function write($id, $data) { > $result = Cache::write($id, $data, $this->cacheKey); > if ($result) { > return parent::write($id, $data); > } > return false; > } > > // destroy a session. > public function destroy($id) { > $result = false; //simulate Cache::delete fails > if ($result) { > return parent::destroy($id); > } > return false; > } > > // removes expired sessions. > public function gc($expires = null) { > return Cache::gc($this->cacheKey) && parent::gc($expires); > } > } > > > And in the database, try modify your current session with time (in data), > and expires to a earlier time. You should run into infinity loop in the > next run. > > ----------------------------------- > > In the end, we fix it by issue delete on both Cache and RDS session data > regardless if Cache succeed or not: > > public function destroy($id) { > //Delete, regardless of cache succeed or not (so to prevent infinity loop) > Cache::delete($id, $this->cacheKey); > return parent::destroy($id); > } > > > *Suggestion: To prevent someone from having this issue again, I think > it's best if you can update your documentation at * > http://book.cakephp.org/2.0/en/development/sessions.html#creating-a-custom-session-handler > . > > Thanks! > /Lionel > -- Like Us on FaceBook https://www.facebook.com/CakePHP Find us on Twitter http://twitter.com/CakePHP --- You received this message because you are subscribed to the Google Groups "CakePHP" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/cake-php. For more options, visit https://groups.google.com/groups/opt_out.
