This is what happens (times are just for example). Notice that this ISN'T automatically what might happen.
1 $_SESSION['message'] = "Some Message";
2 $MSG = $_SESSION['message'];
3 header('location: ../Pages/Error.php');
4 echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
5 You do not have buffering, so header and echo go out to the browser.
6 session_destroy();
8 The browser receives the Location header
7 The server destroys the session file.
9 The browser requests the page
10 The server receives the request
11 The server tries to load the session file. Duh! It's not there!
It could go this slightly different other way:
4 echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
5 You have buffering, so nothing gets output.
6 session_destroy();
7 The server destroys the session file.
8 The scripts exits, the buffer is flushed
9 The browser receives the Location header
10 The browser requests the page
11 The server receives the request
12 The server tries to load the session file. Duh! It's not there!
It could go (on some systems) in a more disastrous way, with the session_destroy and the session_start of the second script running into each other so that the second script reads a damaged session and chokes (this should not happen thanks to locking; but locking has its own drawbacks, see below).
A more interesting thing could happen if your first script does not die, but issues a Location
header and keeps working. Data in the session will not be stored until the script terminates, so if the second script gets launched, it will find a non-updated session. But if you activate buffering, the Location will be sent at the end, and the second script will work. So the buffering apparently "solves" what is really a race problem.
Session impact on performances
An even more interesting thing happens on those systems where read/write access to the session file is arbitrated through locking (as it should, since "race conditions" are BAD, as seen above), and you have transparent sessions, so a lot of requests to your framework - even those that need save no session data, maybe needn't even read it - end up piling up one behind the other because they can't run in parallel as long as they're semaphorized by the session file FS lock.
You can easily diagnose this behaviour using Chrome or Firefox Web Tools, seeing as e.g. AJAX calls start asynchronously, but the actual data delivery is serialized:
-----SXXXXXXXX----------
--------SwwwwwwwwwXXX---
-----SwwwwwXXXXX--------
-------SwwwwwXXXXX------
--------SwwwwwwXXX------
|<------------>|
In that case, adding "session_write_close()" immediately after session_start()
, or anyway as soon as possible (in the class constructor for some frameworks) for those files that might need to read the session, but do not change it, will appear to magically speed up your application (the same happens removing any unneeded session_start()'s, but the framework might make this complex to achieve):
-----SXXXXXXXX---
--------SwwXXX---
-----SwwXXXXX----
-------SwXXXXX---
--------SwXXX----
|<----->| "perceived" user time goes down a good 40%