rfc:session-read_only-lazy_write

This is an old revision of the document!


PHP RFC: Revert/extend/postpone original RFC about read_only, lazy_write sessions

This is a proposal to override the decisions taken in the session-lock-ini RFC. Not in the sense of completely rejecting the RFC, but rather redesign the already accepted solutions, namely the 'read_only' and 'lazy_write' options passed to session_start().

The session-lock-ini has IMHO not been handled properly, to say the least. What ended up as accepted from it is mostly unrelated to what it was originally all about (locking options). It lacks a lot of information and has not been given the required attention for something as critical as Sessions - a fundamental feature in most web applications.

As a result, we have a solution that is broken by design and this is an attempt to fix it before there's no way going back from it.

Introduction

The problems with the already accepted solutions are the following:

read_only

The name itself is highly misleading, especially for the context in which it is used.

What this option does is to cause session_start() to read the session data, populate the $_SESSION super-global and close the session immediately afterwards. However, nothing in the following code implies such behavior:

session_start(['read_only' => TRUE]);

What any programmer would assume from the above code with no prior knowledge about it, is the already popular meaning of the term "read-only" in computing, or in this context - start a session for which the data is not allowed to be modified. In fact, it is so natural to assume a read-only mode, that I had read the RFC multiple times and yet it took somebody actually telling me that this is a “start-read-and-close” functionality instead.

This could and will lead to a lot of confusion, which in turn will result in a lot of malfunctioning userland code. Assume concurrency with the same session ID in the following example:

// $_SESSION['logged_in'] has been set in a previous request
Request 1: session_start(['read_only' => TRUE]);
Request 2: session_start(); unset($_SESSION['logged_in']); session_write_close();
Request 1: if ($_SESSION['logged_in']) { /* logic */ } // evaluates to TRUE

This is downright dangerous, yet it is very easy to fall into that trap.

Furthermore, using the 'read_only' name for 'start-read-and-close' functionality prevents implementing a read-only session mode in the future (have a look at the future scope section), for which it would be a perfect fit.

lazy_write

The issues with this option are more diverse, but if it has to be described in one word, that would be: incomplete.

There is little reason for the option to exist as is in the first place. It is mostly a performance improvement instead of a functional change. I'm saying “mostly”, because of a very important detail that has not been addressed - custom session handlers.

1. Because it was designed as a function argument only (and not an INI setting), there is no API to tell users if/when 'lazy_write' is currently used.

I understand this is because users don't like INI settings and that there are way too many of them for sessions already. This is a valid argument of course, but it completely ignores the fact that INIs exist for a reason and they are a necessity in some cases. This is one of those cases.

2. The RFC describes that with 'lazy_write' set to TRUE, if no change was made to session data, then PS_UPDATE_FUNC() will be called instead of PS_WRITE_FUNC(). However, it only talks about internal implementation and fails to address (or at least mention) that a custom session handler should now also have an update() method.

This in turn implies that update() is added to SessionHandlerInterface, which is a major breaking change and it is completely unclear how that is handled with pre-PHP5.4-style save handlers that don't implement SessionHandlerInterface.

It is the kind of change that IMO should've been left for PHP6, where 'lazy_write' could be safely implemented as mandatory, non-optional behavior and without that much concerns about breaking BC.

Proposal

On 'read_only'

Completely drop the current 'read_only' functionality

As described above, the currently existing 'read_only' is highly misleading, probably even to the extent that some of the people who voted for it didn't understand what it meant. If that turns out to be true, or if this RFC manages to change opinions on it, then dropping the whole thing altogether should be an option.

Rename the current 'read_only' option

If the feature is to be retained, it should be renamed to a standalone function with a better name. It must be descriptive enough and at the very least - intuitive.

In order to be consistent with the new ability for session_start() to accept options (INI or not) in an array, both session_start() and the new function should accept/share the same arguments:

bool function session_start_close(array $options = NULL)

Note: session_start_close() is an example name, actual name is the subject of discussion - feedback is necessary.

Reserve the 'read_only' name for future functionality

Please refer to the Future scope section.

Note: Voting here will be only for reserving the 'read_only' name and not the feature specifics.

On 'lazy_write'

Postpone for PHP 6

Because of the breaking changes that it introduces to userland session handlers and given the importance of sessions, this would make a lot of sense.

Keep it, but provide the necessary tools to work around or with it

If it is decided to keep the feature, the least it could be done is to complete it. This could involve any (and multiple) of the following, subject to feedback from discussion:

  • Introduce a 'session.lazy_write' option, defaulting to FALSE.
  • SessionHandlerInterface::__construct(array $options = NULL) as a way to handle options passed to session_start(). Each option should be set as a property.
  • bool SessionHandlerInterface::update($session_id)
  • Handle PS_UPDATE_FUNC() via SessionHandlerInterface::open() and add a new parameter to determine wheter only a timestamp update should be performed.
  • Somehow detect when the userland implementation doesn't have an update() method and work around it.
    • Trigger an E_WARNING in this case.
  • Ignore 'lazy_write' for userland implementations.
  • Document it as a backwards-incompatible change.

Where SessionHandlerInterface is mentioned above, it of course also means implementing the same feature in the SessionHandler class.

Backward Incompatible Changes

This RFC aims to revert unexpected backwards incompatible changes that are supposed to be released with PHP 5.6.

  • read_only
    • If dropped or renamed before PHP 5.6: none.
    • If dropped or renamed after PHP 5.6: in cases where it was used, a performance hit is expected.
    • If kept as is: forward-compatibility will be affected.
  • lazy_write
    • If postponed for PHP 6 (which at this time means dropped from PHP 5.6): none.
    • If kept as is: major.
    • If kept with additions: hard to tell, to be estimated during the discussion.

Proposed PHP Version(s)

PHP 5.6

However, due to Beta 1 approaching, this is subject to change and heavy edits.

Impact to Existing Extensions

ext/session and possibly all extensions providing a session handler.

php.ini Defaults

For 'lazy_write', this could be 'session.lazy_write':

  • hardcoded: 0
  • php.ini-development: 0
  • php.ini-production: 0

Open Issues

TBD: Make sure there are no open issues when the vote starts!

Future Scope

Implement the 'read_only' option for session_start() as a read-only mode of the session. In other words: don't allow session data to be written if session_start(['read_only' => TRUE]) was called.

This would include the following characteristics (only when in read-only mode):

  • Use shared(reader) instead of exclusive(writer) locks.
  • Writing is allowed only for creation of new session IDs.
  • API to detect the mode in userland code.

Proposed Voting Choices

Still in dicussion, but will most likely match the sections of proposal at 100%.

Should require 50% + 1 votes.

Patches and Tests

No patch is available at this time, the ultimate goal is to revert existing ones.

If patches becomes necessary, I'll be looking for a volunteer with Yasuo Oghaki being a likely candidate.

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged to
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature

References

Rejected Features

TBD: Keep this updated with features that were discussed on the mail lists.

rfc/session-read_only-lazy_write.1394907189.txt.gz · Last modified: 2017/09/22 13:28 (external edit)