Index: ext/session/tests/session_set_save_handler_class_011.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_011.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_011.phpt	(revision 0)
@@ -0,0 +1,66 @@
+--TEST--
+Test session_set_save_handler() : shutdown failure
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : shutdown failure ***\n";
+
+class MySession extends SessionHandler {
+	public $num;
+	public $destroyed = false;
+	public function __construct($num) {
+		$this->num = $num;
+		echo "(#$this->num) constructor called\n";
+	}
+	public function __destruct() {
+		echo "(#$this->num) destructor called\n";
+		$this->destroyed = true;
+	}
+	public function write($id, $data) {
+		if ($this->destroyed) {
+			echo "(#$this->num) destroyed, cannot write\n";
+		} else {
+			echo "(#$this->num) writing $id = $data\n";
+		}
+		return parent::write($id, $data);
+	}
+	public function close() {
+		$id = session_id();
+		if ($this->destroyed) {
+			echo "(#$this->num) destroyed, cannot write\n";
+		} else {
+			echo "(#$this->num) closing $id\n";
+		}
+		return parent::close();
+	}
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler, false);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : shutdown failure ***
+(#1) constructor called
+done
+(#1) destructor called
+(#1) destroyed, cannot write
+(#1) destroyed, cannot write
Index: ext/session/tests/session_set_save_handler_class_007.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_007.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_007.phpt	(revision 0)
@@ -0,0 +1,74 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown, reopen
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown, reopen ***\n";
+
+class MySession extends SessionHandler {
+	public $num;
+	public function __construct($num) {
+		$this->num = $num;
+		echo "(#$this->num) constructor called\n";
+	}
+	public function __destruct() {
+		echo "(#$this->num) destructor called\n";
+	}
+	public function finish() {
+		$id = session_id();
+		echo "(#$this->num) finish called $id\n";
+		session_write_close();
+	}
+	public function write($id, $data) {
+		echo "(#$this->num) writing $id = $data\n";
+		return parent::write($id, $data);
+	}
+	public function close() {
+		$id = session_id();
+		echo "(#$this->num) closing $id\n";
+		return parent::close();
+	}
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// explicit close
+$handler->finish();
+
+$handler = new MySession(2);
+session_set_save_handler($handler);
+session_start();
+
+// implicit close (called by shutdown function)
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown, reopen ***
+(#1) constructor called
+(#1) finish called %x
+(#1) writing %x = foo|s:3:"bar";
+(#1) closing %x
+(#2) constructor called
+(#1) destructor called
+done
+(#2) writing %x = foo|s:3:"bar";
+(#2) closing %x
+(#2) destructor called
Index: ext/session/tests/session_set_save_handler_class_004.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_004.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_004.phpt	(revision 0)
@@ -0,0 +1,48 @@
+--TEST--
+Test session_set_save_handler() : default object
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : default object ***\n";
+
+session_set_save_handler(new SessionHandler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+session_start();
+
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : default object ***
+string(32) "%x"
+string(4) "user"
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
Index: ext/session/tests/session_set_save_handler_class_001.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_001.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_001.phpt	(revision 0)
@@ -0,0 +1,68 @@
+--TEST--
+Test session_set_save_handler() : basic class wrapping existing handler
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : basic class wrapping existing handler ***\n";
+
+class MySession extends SessionHandler {
+	public $i = 0;
+	public function open($path, $name) {
+		++$this->i;
+		echo 'Open ', session_id(), "\n";
+		return parent::open($path, $name);
+	}
+	public function read($key) {
+		++$this->i;
+		echo 'Read ', session_id(), "\n";
+		return parent::read($key);
+	}
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+$_SESSION['foo'] = "hello";
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : basic class wrapping existing handler ***
+Open 
+Read %x
+string(32) "%x"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+Open %x
+Read %x
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
Index: ext/session/tests/session_set_save_handler_class_013.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_013.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_013.phpt	(revision 0)
@@ -0,0 +1,56 @@
+--TEST--
+Test session_set_save_handler() : incorrect arguments for existing handler close
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : incorrect arguments for existing handler close ***\n";
+
+class MySession extends SessionHandler {
+	public $i = 0;
+	public function open($path, $name) {
+		++$this->i;
+		echo 'Open ', session_id(), "\n";
+		return parent::open($path, $name);
+	}
+	public function read($key) {
+		++$this->i;
+		echo 'Read ', session_id(), "\n";
+		return parent::read($key);
+	}
+	public function close() {
+		return parent::close(false);
+	}
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incorrect arguments for existing handler close ***
+Open 
+Read %x
+string(32) "%x"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+
+Warning: SessionHandler::close() expects exactly 0 parameters, 1 given in %s on line %d
Index: ext/session/tests/session_set_save_handler_class_009.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_009.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_009.phpt	(revision 0)
@@ -0,0 +1,62 @@
+--TEST--
+Test session_set_save_handler() : implicit shutdown
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : implicit shutdown ***\n";
+
+class MySession extends SessionHandler {
+	public $num;
+	public function __construct($num) {
+		$this->num = $num;
+		echo "(#$this->num) constructor called\n";
+	}
+	public function __destruct() {
+		echo "(#$this->num) destructor called\n";
+	}
+	public function finish() {
+		$id = session_id();
+		echo "(#$this->num) finish called $id\n";
+		$this->shutdown();
+	}
+	public function write($id, $data) {
+		echo "(#$this->num) writing $id = $data\n";
+		return parent::write($id, $data);
+	}
+	public function close() {
+		$id = session_id();
+		echo "(#$this->num) closing $id\n";
+		return parent::close();
+	}
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// implicit close
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : implicit shutdown ***
+(#1) constructor called
+done
+(#1) writing %x = foo|s:3:"bar";
+(#1) closing %x
+(#1) destructor called
Index: ext/session/tests/session_set_save_handler_class_010.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_010.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_010.phpt	(revision 0)
@@ -0,0 +1,63 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown function
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown function ***\n";
+
+class MySession extends SessionHandler {
+	public $num;
+	public function __construct($num) {
+		$this->num = $num;
+		echo "(#$this->num) constructor called\n";
+	}
+	public function __destruct() {
+		echo "(#$this->num) destructor called\n";
+	}
+	public function finish() {
+		$id = session_id();
+		echo "(#$this->num) finish called $id\n";
+		session_write_close();
+	}
+	public function write($id, $data) {
+		echo "(#$this->num) writing $id = $data\n";
+		return parent::write($id, $data);
+	}
+	public function close() {
+		$id = session_id();
+		echo "(#$this->num) closing $id\n";
+		return parent::close();
+	}
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler, false);
+register_shutdown_function(array($handler, 'finish'));
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown function ***
+(#1) constructor called
+done
+(#1) finish called %x
+(#1) writing %x = foo|s:3:"bar";
+(#1) closing %x
+(#1) destructor called
Index: ext/session/tests/session_set_save_handler_class_006.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_006.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_006.phpt	(revision 0)
@@ -0,0 +1,54 @@
+--TEST--
+Test session_set_save_handler() : using objects in close
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : using objects in close ***\n";
+
+class MySession7_Foo {
+	public $state = 'ok';
+	function __destruct() {
+		$this->state = 'destroyed';
+	}
+}
+
+class MySession7 extends SessionHandler {
+	public $foo;
+	public function close() {
+		var_dump($this->foo);
+		@var_dump($GLOBALS['bar']);
+		return parent::close();
+	}
+}
+
+$bar = new MySession7_Foo;
+$handler = new MySession7;
+$handler->foo = new MySession7_Foo;
+session_set_save_handler($handler);
+session_start();
+
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : using objects in close ***
+object(MySession7_Foo)#%d (%d) {
+  ["state"]=>
+  string(2) "ok"
+}
+object(MySession7_Foo)#%d (%d) {
+  ["state"]=>
+  string(2) "ok"
+}
Index: ext/session/tests/session_set_save_handler_class_003.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_003.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_003.phpt	(revision 0)
@@ -0,0 +1,78 @@
+--TEST--
+Test session_set_save_handler() : inheritance
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : inheritance ***\n";
+
+class MySession3 extends SessionHandler {
+	public $i = 0;
+	public function open($path, $name) {
+		++$this->i;
+		return parent::open($path, $name);
+	}
+	public function read($key) {
+		++$this->i;
+		return parent::read($key);
+	}
+}
+
+class MySession4 extends MySession3 {
+	public function write($id, $data) {
+		$this->i = "hai";
+		return parent::write($id, $data);
+	}
+}
+
+$handler = new MySession3;
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+session_write_close();
+session_unset();
+
+session_start();
+
+var_dump($_SESSION, $handler->i);
+
+session_write_close();
+session_unset();
+
+$handler = new MySession4;
+session_set_save_handler($handler);
+
+session_start();
+
+session_write_close();
+session_unset();
+
+var_dump(session_id(), $_SESSION, $handler->i);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : inheritance ***
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+int(4)
+string(32) "%x"
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+string(3) "hai"
Index: ext/session/tests/session_set_save_handler_class_012.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_012.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_012.phpt	(revision 0)
@@ -0,0 +1,59 @@
+--TEST--
+Test session_set_save_handler() : incorrect arguments for existing handler open
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : incorrect arguments for existing handler open ***\n";
+
+class MySession extends SessionHandler {
+	public $i = 0;
+	public function open($path, $name) {
+		++$this->i;
+		echo 'Open ', session_id(), "\n";
+		return parent::open();
+	}
+	public function read($key) {
+		++$this->i;
+		echo 'Read ', session_id(), "\n";
+		return parent::read($key);
+	}
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incorrect arguments for existing handler open ***
+Open 
+
+Warning: SessionHandler::open() expects exactly 2 parameters, 0 given in %s on line %d
+Read %x
+
+Warning: SessionHandler::read(): Parent session handler is not open in %s on line %d
+string(32) "%x"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+
+Warning: Unknown: Parent session handler is not open in Unknown on line 0
+
+Warning: Unknown: Parent session handler is not open in Unknown on line 0
Index: ext/session/tests/session_set_save_handler_class_008.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_008.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_008.phpt	(revision 0)
@@ -0,0 +1,65 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown ***\n";
+
+class MySession extends SessionHandler {
+	public $num;
+	public function __construct($num) {
+		$this->num = $num;
+		echo "(#$this->num) constructor called\n";
+	}
+	public function __destruct() {
+		echo "(#$this->num) destructor called\n";
+	}
+	public function finish() {
+		$id = session_id();
+		echo "(#$this->num) finish called $id\n";
+		session_write_close();
+	}
+	public function write($id, $data) {
+		echo "(#$this->num) writing $id = $data\n";
+		return parent::write($id, $data);
+	}
+	public function close() {
+		$id = session_id();
+		echo "(#$this->num) closing $id\n";
+		return parent::close();
+	}
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// explicit close
+$handler->finish();
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown ***
+(#1) constructor called
+(#1) finish called %x
+(#1) writing %x = foo|s:3:"bar";
+(#1) closing %x
+done
+(#1) destructor called
Index: ext/session/tests/session_set_save_handler_class_005.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_005.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_005.phpt	(revision 0)
@@ -0,0 +1,54 @@
+--TEST--
+Test session_set_save_handler() : incomplete implementation
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : incomplete implementation ***\n";
+
+class MySession6 extends SessionHandler {
+	public function open($path, $name) {
+		// don't call parent
+		return true;
+	}
+
+	public function read($id) {
+		// should error because parent::open hasn't been called
+		return parent::read($id);
+	}
+}
+
+$handler = new MySession6;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incomplete implementation ***
+
+Warning: SessionHandler::read(): Parent session handler is not open in %s/session_set_save_handler_class_005.php on line %d
+string(32) "%x"
+string(4) "user"
+array(0) {
+}
+
+Warning: SessionHandler::write(): Parent session handler is not open in %s/session_set_save_handler_class_005.php on line %d
+
+Warning: SessionHandler::close(): Parent session handler is not open in %s/session_set_save_handler_class_005.php on line %d
Index: ext/session/tests/session_set_save_handler_class_002.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_002.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_002.phpt	(revision 0)
@@ -0,0 +1,113 @@
+--TEST--
+Test session_set_save_handler() : full handler implementation
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : full handler implementation ***\n";
+
+class MySession2 extends SessionHandler {
+	public $path;
+
+	public function open($path, $name) {
+		if (!$path) {
+			$path = '/tmp';
+		}
+		$this->path = $path . '/u_sess_' . $name;
+		return true;
+	}
+
+	public function close() {
+		return true;
+	}
+
+	public function read($id) {
+		return @file_get_contents($this->path . $id);
+	}
+
+	public function write($id, $data) {
+		return file_put_contents($this->path . $id, $data);
+	}
+
+	public function destroy($id) {
+		@unlink($this->path . $id);
+	}
+
+	public function gc($maxlifetime) {
+		foreach (glob($this->path . '*') as $filename) {
+			if (filemtime($filename) + $maxlifetime < time()) {
+				@unlink($filename);
+			}
+		}
+		return true;
+	}
+}
+
+$handler = new MySession2;
+session_set_save_handler(array($handler, 'open'), array($handler, 'close'),
+	array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'));
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : full handler implementation ***
+string(32) "%x"
+string(4) "user"
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+string(32) "%x"
+string(4) "user"
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
+array(1) {
+  ["foo"]=>
+  string(5) "hello"
+}
Index: ext/session/tests/session_set_save_handler_class_014.phpt
===================================================================
--- ext/session/tests/session_set_save_handler_class_014.phpt	(revision 0)
+++ ext/session/tests/session_set_save_handler_class_014.phpt	(revision 0)
@@ -0,0 +1,32 @@
+--TEST--
+Test session_set_save_handler() : calling default handler when save_handler=user
+--INI--
+session.save_handler=user
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/* 
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c 
+ */
+
+echo "*** Testing session_set_save_handler() : calling default handler when save_handler=user ***\n";
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new SessionHandler;
+session_set_save_handler($handler);
+
+session_start();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : calling default handler when save_handler=user ***
+
+Fatal error: SessionHandler::open(): Called default SessionHandler but session.save_handler is user in Unknown on line %d
+
+Fatal error: Unknown: Called default SessionHandler but session.save_handler is user in Unknown on line %d
