@@ -510,54 +510,51 @@ private function doRead($sessionId)
510
510
$ selectSql = $ this ->getSelectSql ();
511
511
$ selectStmt = $ this ->pdo ->prepare ($ selectSql );
512
512
$ selectStmt ->bindParam (':id ' , $ sessionId , \PDO ::PARAM_STR );
513
- $ selectStmt ->execute ();
514
513
515
- $ sessionRows = $ selectStmt ->fetchAll (\PDO ::FETCH_NUM );
514
+ do {
515
+ $ selectStmt ->execute ();
516
+ $ sessionRows = $ selectStmt ->fetchAll (\PDO ::FETCH_NUM );
516
517
517
- if ($ sessionRows ) {
518
- if ($ sessionRows [0 ][1 ] + $ sessionRows [0 ][2 ] < time ()) {
519
- $ this ->sessionExpired = true ;
518
+ if ($ sessionRows ) {
519
+ if ($ sessionRows [0 ][1 ] + $ sessionRows [0 ][2 ] < time ()) {
520
+ $ this ->sessionExpired = true ;
520
521
521
- return '' ;
522
- }
522
+ return '' ;
523
+ }
523
524
524
- return is_resource ($ sessionRows [0 ][0 ]) ? stream_get_contents ($ sessionRows [0 ][0 ]) : $ sessionRows [0 ][0 ];
525
- }
525
+ return is_resource ($ sessionRows [0 ][0 ]) ? stream_get_contents ($ sessionRows [0 ][0 ]) : $ sessionRows [0 ][0 ];
526
+ }
526
527
527
- if (self ::LOCK_TRANSACTIONAL === $ this ->lockMode && 'sqlite ' !== $ this ->driver ) {
528
- // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
529
- // until other connections to the session are committed.
530
- try {
531
- $ insertStmt = $ this ->pdo ->prepare (
532
- "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) "
533
- );
534
- $ insertStmt ->bindParam (':id ' , $ sessionId , \PDO ::PARAM_STR );
535
- $ insertStmt ->bindValue (':data ' , '' , \PDO ::PARAM_LOB );
536
- $ insertStmt ->bindValue (':lifetime ' , 0 , \PDO ::PARAM_INT );
537
- $ insertStmt ->bindValue (':time ' , time (), \PDO ::PARAM_INT );
538
- $ insertStmt ->execute ();
539
- } catch (\PDOException $ e ) {
540
- // Catch duplicate key error because other connection created the session already.
541
- // It would only not be the case when the other connection destroyed the session.
542
- if (0 === strpos ($ e ->getCode (), '23 ' )) {
543
- // Retrieve finished session data written by concurrent connection. SELECT
544
- // FOR UPDATE is necessary to avoid deadlock of connection that starts reading
545
- // before we write (transform intention to real lock).
546
- $ selectStmt ->execute ();
547
- $ sessionRows = $ selectStmt ->fetchAll (\PDO ::FETCH_NUM );
548
-
549
- if ($ sessionRows ) {
550
- return is_resource ($ sessionRows [0 ][0 ]) ? stream_get_contents ($ sessionRows [0 ][0 ]) : $ sessionRows [0 ][0 ];
528
+ if (self ::LOCK_TRANSACTIONAL === $ this ->lockMode && 'sqlite ' !== $ this ->driver ) {
529
+ // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
530
+ // until other connections to the session are committed.
531
+ try {
532
+ $ insertStmt = $ this ->pdo ->prepare (
533
+ "INSERT INTO $ this ->table ( $ this ->idCol , $ this ->dataCol , $ this ->lifetimeCol , $ this ->timeCol ) VALUES (:id, :data, :lifetime, :time) "
534
+ );
535
+ $ insertStmt ->bindParam (':id ' , $ sessionId , \PDO ::PARAM_STR );
536
+ $ insertStmt ->bindValue (':data ' , '' , \PDO ::PARAM_LOB );
537
+ $ insertStmt ->bindValue (':lifetime ' , 0 , \PDO ::PARAM_INT );
538
+ $ insertStmt ->bindValue (':time ' , time (), \PDO ::PARAM_INT );
539
+ $ insertStmt ->execute ();
540
+ } catch (\PDOException $ e ) {
541
+ // Catch duplicate key error because other connection created the session already.
542
+ // It would only not be the case when the other connection destroyed the session.
543
+ if (0 === strpos ($ e ->getCode (), '23 ' )) {
544
+ // Retrieve finished session data written by concurrent connection by restarting the loop.
545
+ // We have to start a new transaction as a failed query will mark the current transaction as
546
+ // aborted in PostgreSQL and disallow further queries within it.
547
+ $ this ->rollback ();
548
+ $ this ->beginTransaction ();
549
+ continue ;
551
550
}
552
551
553
- return '' ;
552
+ throw $ e ;
554
553
}
555
-
556
- throw $ e ;
557
554
}
558
- }
559
555
560
- return '' ;
556
+ return '' ;
557
+ } while (true );
561
558
}
562
559
563
560
/**
0 commit comments