ZF-1325: "Unwritable session.save_path" when using defaults in Zend_Session and php.ini
Description
<?php
set_include_path(get_include_path().PATH_SEPARATOR.'/path/to/zend/framework');
require_once 'Zend/Session.php';
Zend_Session::start();
?>
produces the following exception when session.save_path is not set in php.ini:
Uncaught exception 'Zend_Session_Exception' with message 'Unwritable session.save_path: ' in /path/to/zend/framework/Zend/Session.php:217
According to the PHP manual (http://nl2.php.net/manual/nl/…) session.save_path should default to "/tmp", but Zend_Session still complains. The following code works, but the ini_set call shouldn't be necessary.
<?php
set_include_path(get_include_path().PATH_SEPARATOR.'/path/to/zend/framework');
require_once 'Zend/Session.php';
ini_set('session.save_path','/tmp');
Zend_Session::start();
?>
Comments
Posted by Chris van der Wel (kritz) on 2007-04-28T15:36:38.000+0000
added code blocks.
Posted by Darby Felton (darby) on 2007-04-30T16:00:12.000+0000
Looking at the code, I see in Zend/Session.php at the end of the {{setOptions()}} method:
But when I look at the www.php.net/manual/en/ref.session.php" rel="nofollow">PHP manual entry I see:
bq. session.save_path defines the argument which is passed to the save handler. If you choose the default files handler, this is the path where the files are created. Defaults to /tmp. See also session_save_path(). bq. There is an optional N argument to this directive that determines the number of directory levels your session files will be spread around in. For example, setting to '5;/tmp' may end up creating a session file and location like /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If . In order to use N you must create all of these directories before use. A small shell script exists in ext/session to do this, it's called mod_files.sh. Also note that if N is used and greater than 0 then automatic garbage collection will not be performed, see a copy of php.ini for further information. Also, if you use N, be sure to surround session.save_path in "quotes" because the separator (\;) is also used for comments in php.ini.
If we consider it a good design decision that Zend_Session throws an Exception if the session path is not writable, then it must also check all of the child directories of the session.save_path when using the optional N argument. I think that this is not a good option, however, and I tend to question the sensibility of throwing an Exception at this point in the code for the purpose of verifying the session.save_path.
Posted by Darby Felton (darby) on 2007-04-30T16:01:26.000+0000
Volley to [~ralph] for additional comment.
Posted by Ralph Schindler (ralph) on 2007-05-08T11:26:07.000+0000
Ok, after reading through the ext/session C, I know whats going on and why its going on. session_start(), regardless of whether or not it actually does start or not, will set its internal state to active. Which means, session_write_close (effectively) will run at RSHUTDOWN, thus changing the state of ext/session.
Also, the following code has the added benefit of being able to throw exceptions on ANY mod_handler ext/session decides to use, be it mm, files, db, or memcached. The idea as always, is that session_start should emit nothing from PHP and should start clean, otherwise, we should throw an exception as developers might want to be able to handle it at bootstrap time.
Posted by Ralph Schindler (ralph) on 2007-05-08T12:28:14.000+0000
ABOVE IS PROOF-OF-CONCEPT ONLY, see the fixes in the code
Fisheye tab above or:
SVN r4763
Posted by Darby Felton (darby) on 2007-05-09T14:37:13.000+0000
Confirmed as fixed. Thanks to [~ralph]!