From:             amirlaher at yahoo dot co dot uk
Operating system: Debian Sarge,Ubuntu
PHP version:      5.2.1
PHP Bug Type:     Session related
Bug description:  session written AFTER global variables have been destroyed

Description:
------------
This issue affects custom session handlers (as defined with
session_set_save_handler()), in which the write function attempts to access
a *global object*.

When upgrading a custom session handler (calling a perl daemon), from
php5.1 to php5.2, the session was never written owing to a "Call to a
member function xxx() on a non-object" error.

This seemingly occurs because global objects get destructed *before*
session_write_close() is called, during php's shutdown sequence.

I worked around the issue using
register_shutdown_function("session_write_close"); near the top of the
script.
register_shutdown_function() does take effect when a script is terminated
using exit(); I would have to call "session_write_close();" after having
finished writing to the session.
This error also still springs up sometimes when the memory limit is
reached.

This behaviour-change was painful but could be an intentional change by
the php team (?) I am reporting it because it may be an unintentional
change, and I have seen that it has also affected other users including
Drupal users
(e.g. this Zend Forums thread:
http://www.zend.com/forums/index.php?t=msg&th=3464
and Drupal: http://drupal.org/node/92802)

Cheers
Amir

Reproduce code:
---------------
<?php
//apologies: this is more than 20 lines.
//I have amended the php manual example to use a rudimentary object, just
for illustration purposes.
class sess {
        var $savePath;
        var $id;
        function getSavePath() {
                return $this->savePath;
        }
        function setSavePath($savePath) {
                $this->savePath= $savePath;
        }
        function getFilePath() {
                return $this->getSavePath().'/sess_'.$this->getId();
        }
        function getId() {
                return $this->id;
        }
        function setId($id) {
                $this->id= $id;
        }
}

function open($savePath, $session_name)
{
  global $sess;
  $sess= new sess;
  $sess->setSavePath('/tmp');
  return(true);
}

function close()
{
  return(true);
}

function read($id)
{
  global $sess;
  $sess->setId($id);
  if(file_exists($sess->getFilePath())) {
        return (string) file_get_contents($sess->getFilePath());
  }
}

function write($id, $sess_data)
{
  global $sess;
  if ($fp = fopen($sess->getFilePath(), "w")) {
    $return = fwrite($fp, $sess_data);
    fclose($fp);
    return $return;
  } else {
    return(false);
  }

}

function destroy($id){
  global $sess;
  return(unlink($sess->getFilePath()));
}

function gc($maxlifetime)
{
  global $sess;
  foreach (glob($sess->getSavePath()."/sess_*") as $filename) {
    if (filemtime($filename) + $maxlifetime < time()) {
      unlink($filename);
    }
  }
  return true;
}
session_set_save_handler("open", "close", "read", "write", "destroy",
"gc");
session_start();
print "session id : " . session_id() . "<br>";
if(!$_SESSION['hi']) {
        $_SESSION['hi']='ho';
} else {
        $_SESSION['ts']=time();
}
print "session data: <pre>"; print_r($_SESSION);
print "\nclass data: \n "; print_r($sess);


Expected result:
----------------
session written ok

Actual result:
--------------
session id : 8b2596bea65174ce950bb47140edfe2a
session data:

Array
(
    [hi] => ho
)

class data: 
 sess Object
(
    [savePath] => /tmp
    [id] => 8b2596bea65174ce950bb47140edfe2a
)


Fatal error:  Call to a member function getFilePath() on a non-object in
/var/www/sesstest.php on line 52



-- 
Edit bug report at http://bugs.php.net/?id=41230&edit=1
-- 
Try a CVS snapshot (PHP 4.4): 
http://bugs.php.net/fix.php?id=41230&r=trysnapshot44
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=41230&r=trysnapshot52
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=41230&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=41230&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=41230&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=41230&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=41230&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=41230&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=41230&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=41230&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=41230&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=41230&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=41230&r=globals
PHP 3 support discontinued:   http://bugs.php.net/fix.php?id=41230&r=php3
Daylight Savings:             http://bugs.php.net/fix.php?id=41230&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=41230&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=41230&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=41230&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=41230&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=41230&r=mysqlcfg

Reply via email to