Found error handling problems with PEAR's SOAP_Server
| From: | Jon Day | Date: | Mon, 12 Jan 2004 00:35:59 +0000 |
| Subject: | Found error handling problems with PEAR's SOAP_Server | ||
| Groups: | php.soap | ||
| Request: | Send a blank email to php-soap+get-1308@lists.php.net to get a copy of this message | ||
Hello There:
I would like to start out by saying that I am glad that this community
exists - and I am very grateful for everyone's contributions. I have just
spent the last day in heavy SOAP development with PEAR and discovered a
bug/wrinkle that causes major problems when dealing with error handling.
In short, the Server.php file's SOAP_ServerErrorHandler function does not
check the error_reporting level before it sets $soap_server_fault. This has
become very annoying because a simple E_NOTICE error causes the server to
return a soap fault!
My first thought was to use php's error_reporting() feature to ignore
E_NOTICE errors, only to realize that the library ignores this setting
completely when handling an error (for two reasons: 1. There is no code in
the function SOAP_ServerErrorHandler to check the error_reporting level; 2.
Even if such code existed, you would have to set error_reporting(E_<blah>)
in all your server methods, since your server methods are called by
SOAP_Server with the @ symbol, which sets error_reporting to nothing for the
scope of the method).
The PHP manual suggests the following when using custom error handlers:
"error_reporting() settings will have no effect and your error handler will
be called regardless - however you are still able to read the current value
of error_reporting and act appropriately. Of particular note is that this
value will be 0 if the statement that caused the error was prepended by the
@ error-control operator."
That means that as of right now, if you have a line of code executed that
looks like this:
$file = @file('/path/to/a/non/existant/file');
.. then your soap server will return a soap fault, regarless of what
error_reporting is set to! Even when the above errorsome "file" funciton
call is prefixed with the @ symbol!
How do we solve these issues?
There are two changes that need to be made to the Server.php file. First,
removing the @ error-control operator on all the server method calling code
(they are not needed because a custom error handler was set using
set_error_handler, which catches errors anyway... so all these symbols
actually do is change the error_reporting level in the scope of the called
server method. Second is to update the SOAP_ServerErrorHandler callback
function to check the level of error_reporting and decide whether or not an
error should be logged to the global $soap_server_fault (which is later
check for and returned as a soap fault to the client if set).
In case you didn't realize yet, I'm referring to the Server.php which has
moved to the ZEND_ENGINE_1 branch of cvs. (v1.44.2.1 2003/12/20 from CVS). I
have a clean patched version of the file for the cvs maintainer(s) (Shane?).
Please let me know who I should send the patched file to -
Any comments welcome!
Thanks for listening,
Jon
PS Below is the result of cvs diff after my modifications for the Server.php
file in question:
===================================================================
RCS file: /repository/pear/SOAP/Server.php,v
retrieving revision 1.44.2.1
diff -r1.44.2.1 Server.php
32,34c32,38
< $detail = "Errno: $errno\nFilename: $filename\nLineno: $linenum\n";
< // XXX very strange behaviour with error handling if we =& here.
< $soap_server_fault = new SOAP_Fault($errmsg, 'Server', 'PHP',
$detail);
---
> // only set the $soap_server_fault global if the the error_reporting
level says so
> // added by Jon Day <php.soap@jonathanday.com>
> if ((error_reporting() & $errno) == $errno) {
> $detail = "Errno: $errno\nFilename: $filename\nLineno:
$linenum\n";
> // XXX very strange behaviour with error handling if we =& here.
> $soap_server_fault = new SOAP_Fault($errmsg, 'Server', 'PHP',
$detail);
> }
239c243
< $ret = @call_user_func_array(array(&$this->soapobject,
$methodname),$args);
---
> $ret = call_user_func_array(array(&$this->soapobject,
$methodname),$args);
241c245
< $ret = @call_user_func_array($methodname,$args);
---
> $ret = call_user_func_array($methodname,$args);
246c250
< $ret = @call_user_func(array(&$this->soapobject,
$methodname));
---
> $ret = call_user_func(array(&$this->soapobject,
$methodname));
248c252
< $ret = @call_user_func($methodname);
---
> $ret = call_user_func($methodname);