php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #34430 Custom handler + object destruction
Submitted: 2005-09-08 17:17 UTC Modified: 2005-09-10 23:21 UTC
From: jpleveille at unimasoft dot com Assigned:
Status: Not a bug Package: Session related
PHP Version: 5.0.5 OS: Windows XP SP2
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: jpleveille at unimasoft dot com
New email:
PHP Version: OS:

 

 [2005-09-08 17:17 UTC] jpleveille at unimasoft dot com
Description:
------------
If this is a not a bug, sorry. But I think the behaviors of script execution and object destruction changed in PHP 5.0.5 without notice.

I created a session handler which uses a database object to query a MySQL DB to load/save sessions. The object is a PEAR::DB instance created with mysqli factory; the session handler is a simple object with methods being passed to session_set_save_handler(). The session object has a reference to the database object to query the database.

A problem started to occur when upgrading from PHP 5.0.4 to PHP 5.0.5 on both Windows (XP SP2) and Linux. On Linux, it is not possible to close a session using my own session handler because the database object is already destroyed (read disconnected - the object was still there but not connected - I suspect the use of OO interface of mysqli in PEAR::DB). On Windows, this issue occurs only when functions die() or exit() are used.

Additionally, with E_ALL, I have the following error message:

Unknown: A session is active. You cannot change the session module's ini settings at this time. in Unknown on line 0

Reproduce code:
---------------
My session handler:
class DB_Session
{
  private $db; // instance of PEAR::DB(mysqli)
  public __construct($db) { $this->db = $db; }
  public open($save_path, $session_name); // to open session
  public close(); // to close session
  public read($id); // to read the session data
  public write($id, $sess_data); // to write session data
  public destroy($id); // to delete the session in DB
  public gc($maxlifetime); // my garbage collector
  public start() // to start the session
  {
    ini_set('session.hash_bits_per_character', 5);
    ini_set('session.hash_function', 1); // SHA1
    session_set_save_handler(
        array($this, "open"),
        array($this, "close"),
        array($this, "read"),
        array($this, "write"),
        array($this, "destroy"),
        array($this, "gc")
    );
    session_start();
  }
}

$db = PEAR::connect('mysqli://user:pass@host/db');
$session = new DB_Session($db);

// on Linux, $session->write() raises an error (PEAR::DB
// object disconnected)
// this error occurs in Windows when die() or exit is called

Expected result:
----------------
In PHP 5.0.4, the database object is still connected when the session handler is called to write the session data. I expected the same behavior in PHP 5.0.5, i.e.:

- database object is created
- session object is created, database object passed to constructor
- session is read (ok)
- script execution ends, session is written (ok)
- session is closed (does nothing, db object might be used elsewhere)

Actual result:
--------------
The script executes correctly, but the session isn't saved because method write() fails to query database to record new session data. I have the following behavior:

- database object is created
- session object is created, database object passed to constructor
- session is read (ok)
- script execution ends, session is written (failed - db object disconnected!)

Note that I encountered this error in Windows ONLY when calling exit() or die(). I encountered this issue in every PHP script execution using the custom session handler on Linux (debian sarge).

I know my database object may be destroyed BEFORE my session object, but it doesn't seem to be the case because I can still access its methods. I think it has something to do with the mysqli object (returned by mysqli_connect()) but I'm not sure (I also noticed PEAR::DB(mysqli) isn't handling the persistent option).

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-09-08 17:19 UTC] jpleveille at unimasoft dot com
In the example, you must read
$db = DB::connect('mysqli://user:pass@host/db');

and not
$db = PEAR::connect('mysqli://user:pass@host/db');

Sorry for this little mistake.
 [2005-09-08 17:29 UTC] sniper@php.net
Call session_write_close() in the object's __destruct()
 [2005-09-08 18:05 UTC] jpleveille at unimasoft dot com
It works. How can this be explained? In PHP 5.0.4 everything was working well and now (in 5.0.5) we have to add this implicit call to session_write_close() in the handler's destructor.
 [2005-09-10 23:21 UTC] sniper@php.net
This is how it's supposed to work. No bug here.

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu May 16 09:01:32 2024 UTC