@@ -180,10 +180,21 @@ public function start()
180180 // Need to apply the config options so they can be ready by session_start
181181 $ this ->initIniOptions ();
182182 $ this ->registerSaveHandler ();
183+ if (isset ($ _SESSION ['new_session_id ' ])) {
184+ // Not fully expired yet. Could be lost cookie by unstable network.
185+ session_commit ();
186+ session_id ($ _SESSION ['new_session_id ' ]);
187+ }
183188 $ sid = $ this ->sidResolver ->getSid ($ this );
184189 // potential custom logic for session id (ex. switching between hosts)
185190 $ this ->setSessionId ($ sid );
186191 session_start ();
192+ if (isset ($ _SESSION ['destroyed ' ])
193+ && $ _SESSION ['destroyed ' ] < time () - $ this ->sessionConfig ->getCookieLifetime ()
194+ ) {
195+ $ this ->destroy (['clear_storage ' => true ]);
196+ }
197+
187198 $ this ->validator ->validate ($ this );
188199 $ this ->renewCookie ($ sid );
189200
@@ -498,7 +509,33 @@ public function regenerateId()
498509 return $ this ;
499510 }
500511
501- $ this ->isSessionExists () ? session_regenerate_id (true ) : session_start ();
512+ if ($ this ->isSessionExists ()) {
513+ // Regenerate the session
514+ session_regenerate_id ();
515+ $ newSessionId = session_id ();
516+ $ _SESSION ['new_session_id ' ] = $ newSessionId ;
517+
518+ // Set destroy timestamp
519+ $ _SESSION ['destroyed ' ] = time ();
520+
521+ // Write and close current session;
522+ session_commit ();
523+
524+ // Called after destroy()
525+ $ oldSession = $ _SESSION ;
526+
527+ // Start session with new session ID
528+ session_id ($ newSessionId );
529+ session_start ();
530+ $ _SESSION = $ oldSession ;
531+
532+ // New session does not need them
533+ unset($ _SESSION ['destroyed ' ]);
534+ unset($ _SESSION ['new_session_id ' ]);
535+ } else {
536+ session_start ();
537+ }
538+
502539 $ this ->storage ->init (isset ($ _SESSION ) ? $ _SESSION : []);
503540
504541 if ($ this ->sessionConfig ->getUseCookies ()) {
0 commit comments