PHP Bugs  
php.net | support | documentation | report a bug | advanced search | search howto | statistics | login

go to bug id or search bugs for  

Bug #41270 session_start warnings caught by error handler produce fatals
Submitted:3 May 2007 6:08pm UTC Modified: 3 May 2007 6:56pm UTC
From:matthew at zend dot com Assigned to:
Status:Bogus Category:Session related
Version:5.2.2 OS:Linux
View/Vote Developer Edit Submission

[3 May 2007 6:08pm UTC] matthew at zend dot com
Description:
------------
In http://bugs.php.net/41253, Ralph Schindler notes an issue with how
session startup errors due to unwritable session.save_path settings
perform. This issue was closed as 'bogus', but I feel that the reviewer
did not fully understand the situation. He commented, "You're trying to
throw an exception when the engine is shutting down, so
you get a pretty much expected fatal error."

The engine is not shutting down at this point, however. As Ralph notes
in the original bug, under normal circumstances, if session.save_path is
not writable, PHP simply emits an E_WARNING, not an E_FATAL, and
continues execution.

In the example he provides, we get radically different behaviour when
using an error handler to trap the E_WARNING and throw it as an
exception -- basically, even if a try/catch block is used, the otherwise
recoverable error now becomes a fatal one.

Please re-examine the issue.

Reproduce code:
---------------
<?

ini_set('session.save_path', '/var/log'); 
set_error_handler('save_handler', E_ALL); 
try { 
    session_start(); 
} catch (Exception $e) { 
    echo $e->getMessage(); 
} 

function save_handler($errno, $errmsg) 
{ 
    throw new Exception('Error caught and thrown as exception: ' .
$errmsg); 
}  

Expected result:
----------------
Error caught and thrown as exception: session_start():
open(/var/log/sess_3e97dad0fe4ce6f285e97593471f2c88, O_RDWR) failed:
Permission denied (13)

Actual result:
--------------
Error caught and thrown as exception: session_start():
open(/var/log/sess_3e97dad0fe4ce6f285e97593471f2c88, O_RDWR) failed:
Permission denied (13)
Fatal error: Exception thrown without a stack frame in Unknown on line
0
[3 May 2007 6:35pm UTC] tony2001@php.net
Once again, in more details:
ext/session writes its data on shutdown (if one doesn't call
session_write_close() explicitly, but this is not the case).
When the extension tries to write the data, it suddenly discovers that
the path is wrong and fails, producing the error. This error is caught
and converted to an exception, which is thrown by the error handler. But
at this point the engine is partly down and there is no active script
(its execution has finished and the engine is shutting down), hence
there is nobody to catch the exception and there is no stack frame
(that's exactly what the message says).

This is similar to following case:
<?php
class foo {
  function __destruct() {
    thrown new Exception("boo");
  }
}

$foo = new Foo;

/* uncomment the line below and the object will be destroyed when there
is an active scope.
though it does not change the fact that an uncaught exception results in
a fatal error.
 */
//unset($foo);
?>

You seem to be expecting the exception to vanish somewhere, but that's
clearly wrong.
[3 May 2007 6:47pm UTC] matthew at zend dot com
Tony -- thanks for the explanation. I have one question, though: from
what you say, it sounds like the error is not being raised until script 
shutdown -- i.e., only when the script is attempting to write the
session. However, that doesn't seem to be the case. If I modify the
reproduce script to add an echo statement after the try/catch block, or
even in the try block *after* the call to session_start, that echo is
never reached.

From observing that behaviour, it *appears* that the exception is being
thrown before script shutdown. What is the explanation behind that
behaviour?
[3 May 2007 6:55pm UTC] matthew at zend dot com
Never mind -- the statements *are* being echoed -- I just didn't see
them as they were in the same line as the exception message.

Thanks for the explanations, Tony.
[3 May 2007 6:56pm UTC] tony2001@php.net
>If I modify the reproduce script to add an echo statement after the 
>try/catch block 

I can see all the echos after the try/catch block.

>or even in the try block *after* the call to
>session_start, that echo is never reached.

No wonder, there is an exception in session_start() either.

>From observing that behaviour, it *appears* that the exception is
>being thrown before script shutdown. 

1) Error caught and thrown as exception: session_start():
open(/var/log/sess_3e97dad0fe4ce6f285e97593471f2c88, O_RDWR) failed:
Permission denied (13)
2) Fatal error: Exception thrown without a stack frame in Unknown on
line 0

1) and 2) are two different exceptions.

RSS feed | show source 

PHP Copyright © 2001-2009 The PHP Group
All rights reserved.
Last updated: Sat Nov 21 10:30:49 2009 UTC