RE: [PHP-DEV] Error handling brainstorming
De : nicolas.gre...@gmail.com [mailto:nicolas.gre...@gmail.com Envoyé : vendredi 24 août 2012 09:24 1) PHP Errors come with a severity code and a string message. You want to handle specific errors in a specific way? You better start writing giant regexes parsing the string messages. This is a problem that could also be addressed with the current error handling mechanism: that would require that any error comes with some unique number for example. Is this possible? Independently of the exception vs classical error discussion, that would be amazing. +1 on error msg numbering. Such an error ID would contain at least two parts, one identifying the code block the error was generating from ('core' or extension name), and a number unique in this context. So, each extension writer could manage its own error numbering space. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
On Fri, 3 Aug 2012, Ferenc Kovacs wrote: Basically Etienne mentioned that the original issue was a good example why would we reconsider throwing exceptions from the core, which is currently discouraged.[2] Stan replied with the idea of turning the current error handling mechanism in php into using Exceptions for everything, but keeping some error types as is/uncatchable. [3] This is going to be the biggest BC break *ever*. Instead of harmless notices and warnings that people will and can (and sometimes should) ignore, the moment any of those happens, the script will suddendly because the exception isn't caught. Andrew: From your mails, it seems that you don't agree with Stan on turning everything but fatals into exceptions[9]. That's a funny one. The only thing that currently makes sense to use an exception for is the E_RECOVERABLE - that is, without potentionally breaking any script that's ever been written. So basically these are our boundaries: - Fatal errors can't be turned into Exceptions, but it was mentioned multiple times, that there are some fatals, which could be turned into E_RECOVERABLE_ERROR. Some, but definitely not many. When we introduced E_RECOVERABLE we had a good look at them all. - Most/all non-fatal errors could be safe to be turned into Exceptions as without explicit measures(try-catch) on the caller's side, it would still stop the execution. And hence break the script... cheers, Derick -- http://derickrethans.nl | http://xdebug.org Like Xdebug? Consider a donation: http://xdebug.org/donate.php twitter: @derickr and @xdebug -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
** The overall mood seems to be that since PHP has an error handler, everyone is free to handle errors any way they want. 2) When everyone starts handling errors in their own way with error handlers, you can't reliably use third party code. You are in your own universe. I think that's the main point that makes any change to the way PHP currently handles errors difficult: The current behavior is to continue the execution flow (except for fatal errors of course) whereas an exception always breaks it. Throwing an exception, either in a custom or in a new internal handler, introduces a major portability + backward compatibility issue. But do you think it could be possible to introduce a per script declaration of the way it has been coded regarding error handling ? We could imagine for example that any script that is coded assuming exceptions instead of errors could be force to declare with a : ?php declare(throw_errors=1); ? or maybe : ?php declare(throw_errors=E_WARNING | E_NOTICE /* | ...*/); 1) PHP Errors come with a severity code and a string message. You want to handle specific errors in a specific way? You better start writing giant regexes parsing the string messages. This is a problem that could also be addressed with the current error handling mechanism: that would require that any error comes with some unique number for example. Is this possible? Independently of the exception vs classical error discussion, that would be amazing. Regards, Nicolas
Re: [PHP-DEV] Error handling brainstorming
2012/8/24 Nicolas Grekas nicolas.grekas+...@gmail.com: ** The overall mood seems to be that since PHP has an error handler, everyone is free to handle errors any way they want. 2) When everyone starts handling errors in their own way with error handlers, you can't reliably use third party code. You are in your own universe. I think that's the main point that makes any change to the way PHP currently handles errors difficult: The current behavior is to continue the execution flow (except for fatal errors of course) whereas an exception always breaks it. Throwing an exception, either in a custom or in a new internal handler, introduces a major portability + backward compatibility issue. I think we should talk first over the general handling and then go into the details (how to handle the different types of errors/warnings etc.) Maybe I repeat some things. What do we want? A) Handling errors with exceptions instead error-handler B) handling warnings/notices in some way. That are 2 completely different things... For A: Errors (something which stops execution) could be just handled as an exception. I see no problem with this: If not handled, they behave like now. For B - the warnings etc. - I suggest something like this: // This is pseudocode: abstract class WarningAbstract implements Exception { public function __construct() { error_log($this-message()..); unset($this); // I just want to say, that the exception is destroyed in any way and so not handled any more } ... } // A warning looks like this - this is created by PHP for example when turning on E_WARNING in php.ini class Warning extends WarningAbstract { } // and when created it does this: if (class_exists('Warning')) { $warning = new Warning(); if (isset($warning)) { throw $warning; } } Logically, when the exception is created the constructor is called. In this example (by default) PHP could handle a warning etc. (write something into a error-log) and then destructs itself, to stop the handling. (Of course this doesn't work now, when unseting myself the object is not unseted; I wrote this code only so that PHP-programmers could understands what I mean.) [Not so important: could be configured like now. If E_WARNING is turned on in the php.ini, PHP creates the default handler for this class itself. If not, the class doesn't exists and so nothing happens. Or I create my own Warning class, and implement my own way to handle the warnings.] This has the big advantage, that we don't need to care about the mentioned different handling of the different type of errors (see above: A, B). I think it is important, that the way how it is done is for every kind of error the same. Now the details: A file-error is defined abstract class FileHandlerWarningAbstract extends if exists Warning // of course if exists is no PHP - just to explain that it should work as a hint for the compiler to create the hierarchy { } The code to create the exception needs to recursively look up: If no FileHandlerWarning exists it must know the hirarchy of it's abstract (in this case the Warning) and look if that class exists. And so on. So you can handle file-errors different from all other warnings without try/catch everything. Not perfect for now, and I think a little bit too complicated, but this is a brainstorming. -- Alex Aulbach -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
The overall mood seems to be that since PHP has an error handler, everyone is free to handle errors any way they want. Everyone is surprisingly ignoring the two giant holes in that theory: 1) PHP Errors come with a severity code and a string message. You want to handle specific errors in a specific way? You better start writing giant regexes parsing the string messages. 2) When everyone starts handling errors in their own way with error handlers, you can't reliably use third party code. You are in your own universe. Stan
Re: [PHP-DEV] Error handling brainstorming
Hi! Have you stopped for a moment to think this opinion through? Look at two Of course not. Why would I bother thinking? It is always safe to assume nobody thinks before writing anything to the list. typical patterns of error handling. The examples below are generalized from my file cache code. Having no cache is exceptional, because 99.999% of the time I run this, there is cache, except the first time when there's not. Tell me again how you using try..catch is very verbose and how you need to supply multiple catch blocks for every kind of exception possible? You are either purposefully exaggerating or not doing it right. if(fileop1() fileop2() fileop3()) { // do valid stuff } else { // do error stuff } It's not that hard. With exceptions: try { fileop1(); fileop2(); fileop3(); normal_actions(); } catch (IOException $e) { exceptional_actions(); } Now imagine fileop1 throws some other exception - note that you have no idea which exceptions are there and nothing guarantees you fileop1 throws only IOException, and by the proposal here, any problem in any code whatsoever results in exception now, even if the problem was in converting log message to utf-8 while writing some log inside some function called by fileop2(). Now your whole app has failed, even though you don't really care about that log message at all. -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
You are either purposefully exaggerating or not doing it right. if(fileop1() fileop2() fileop3()) { // do valid stuff } else { // do error stuff } It's not that hard. I guess it was my mistake that I simplified my actual code for simplicity's sake. Please show me how would my actual code look stuffed in an if statement: try { $cacheBaseFile = Core\CACHE_PATH . '/Compiled/' . \str_replace('\\', '-', $symbolName); // The validator checks whether the cache is fresh. $cacheIsFresh = include $cacheFileBase . '.val.php'; // Attempt to load the cache (it should be there if the validator is there, unless someone messed with the files). if ($cacheIsFresh) { $result = include $cacheFileBase . '.main.php'; } else { $this-generateCache($symbolName); ... } return $result; } catch (IncludeIOError $e) { // One or more of the files were damaged or missing. ... } When you have: 1) comments 2) multiple statements 3) assign variables 4) call functions/methods with long arguments etc. ...you can't just stuff it in an if (op() op() op()) and pretend this is in any way a maintainable code style. With exceptions: try { fileop1(); fileop2(); fileop3(); normal_actions(); } catch (IOException $e) { exceptional_actions(); } Now imagine fileop1 throws some other exception - note that you have no idea which exceptions are there and nothing guarantees you fileop1 throws only IOException, and by the proposal here, any problem in any code whatsoever results in exception now, even if the problem was in converting log message to utf-8 while writing some log inside some function called by fileop2(). Now your whole app has failed, even though you don't really care about that log message at all. Exceptions aren't about log messages, they're about exceptions - error conditions that have to be handled. If my code above generates another type of exception there are only two options: 1) Either I catch that exception because I know how to handle it -or- 2) I don't catch it, and the app should correctly stop right there before data damage is done. I know PHP's model is all messed up, but no one here, I believe, is asking about putting non-error log messages in Exceptions. IO failure is an exception. If your IO operation fails, you can't just log it and plow forward blissfully without handling the problem. Stan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
I know PHP's model is all messed up, but no one here, I believe, is asking about putting non-error log messages in Exceptions. IO failure is an exception. If your IO operation fails, you can't just log it and plow forward blissfully without handling the problem. Stan Exceptions allow you to decide: I know how to handle it - deal with it, I don't know how to handle it - pop up to higher layer who might know I didn't know this case needs to be handled - pop up to handler of last resort, either crash or catch-all and at least present some meaningful info on what happened. That's managable. Of course you can probably do most stuff with error code handling, PEAR_Error Friends, error handlers for really bad stuff. We've been doing this before Exceptions. But wherever it makes sense, I tend to use them. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi! Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? Yes, it is. You can control it, unlike the exception which you can not, unless, again, you wrap everything into try/catch on every kind of exception possible. Have you stopped for a moment to think this opinion through? Look at two typical patterns of error handling. The examples below are generalized from my file cache code. Having no cache is exceptional, because 99.999% of the time I run this, there is cache, except the first time when there's not. Tell me again how you using try..catch is very verbose and how you need to supply multiple catch blocks for every kind of exception possible? With exceptions: try { fileop1(); fileop2(); fileop3(); normal_actions(); } catch (IOException $e) { exceptional_actions(); } Without exceptions: $valid = true; if (fileop1() !== FALSE) { $valid = false; } if ($valid fileop2() !== FALSE) { $valid = false; } if ($valid fileop3() !== FALSE) { $valid = false; } if ($valid) { normal_actions(); } else { exceptional_actions(); } -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
errors, you can't just fread the return value. You *need* to change your execution flow based on that error. Therefore, it is exceptional. That's exactly what I am saying. Exceptions should not be a means of flow control, and that's exactly what are you doing here. I agree that exceptions should not be a means of flow control except when something exceptional has happened. The difference is between what you think is exceptional and what I do. Of course you are welcome to believe what you want to and voice your opinion, but I think I speak for the rest of us when I say, We've heard your opinion, loud and clear. It's okay. Let the rest of us voice our opinions. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Stas, On Tue, Aug 7, 2012 at 1:46 AM, Stas Malyshev smalys...@sugarcrm.comwrote: Hi! circumstance. If it's not, you should be checking for existence first (via file_exists() or is_readable(), etc)... This is exactly how we got into this mess with $x = isset($a['x'])?$a['x']:null; We're trying to get out of this mess and you're proposing to build another mess just like that. A situation like that is not exceptional. It's null either way, therefore no exception should be thrown. (Which is why I said earlier that I wouldn't want most Notices to become exceptions)... errors, you can't just fread the return value. You *need* to change your execution flow based on that error. Therefore, it is exceptional. That's exactly what I am saying. Exceptions should not be a means of flow control, and that's exactly what are you doing here. Exceptions by very definition are a means of flow control. That's their very purpose. The difference here is that it's a means of flow control when an error means you literally can't continue on in the current flow of execution (such as the fopen case). To continue the current flow would break lots of stuff, because it's expecting a resource. Therefore, the resource not being opened is exceptional... Anthony
Re: [PHP-DEV] Error handling brainstorming
2012/8/6 Stas Malyshev smalys...@sugarcrm.com Exceptions are different from PHP errors. For example, if you try to open a file and the file isn't there, throwing exception is a very annoying behavior (yes I know some languages do that, IMO it's wrong). The reason is that it's pretty normal and within normal set of situations to which code should be prepared, so you will either have to obsessively wrap everything with try/catch blocks or do exception typing like Java does. Both options are quite annoying. I think it's much better to just open file and check if the result is OK. Converting it to exception doesn't really improve situation, as if downstream code didn't handle it the upstream probably won't know what to do with that exception either. This leads to code like try { whatever(); } catch(Exception e) {}. I saw tons of that in Java. Even a simple file opening can fail for different kind of reasons (the file doesn't exists, it is not readable, on some OS it could be already opened and thus locked). Most of the time, you don't care the reason, but sometimes you want to be more precise. With exceptions, we have an elegant way to manage all failures as a whole, or to differenciate each reason. But you are right, it could be very annoying to write a lot of try/catch blocks. Maybe we could think about something inspired from Lua's protected call function [1]. A convenient mean to say «OK, I know this expression may raise an exception, but I don't care, discard it silently please. I will check if my variable has been set or not.». [1] : http://www.lua.org/pil/8.4.html
Re: [PHP-DEV] Error handling brainstorming
On 06/08/12 08:43, Amaury Bouchard wrote: 2012/8/6 Stas Malyshev smalys...@sugarcrm.com Exceptions are different from PHP errors. For example, if you try to open a file and the file isn't there, throwing exception is a very annoying behavior (yes I know some languages do that, IMO it's wrong). The reason is that it's pretty normal and within normal set of situations to which code should be prepared, so you will either have to obsessively wrap everything with try/catch blocks or do exception typing like Java does. Both options are quite annoying. I think it's much better to just open file and check if the result is OK. Converting it to exception doesn't really improve situation, as if downstream code didn't handle it the upstream probably won't know what to do with that exception either. This leads to code like try { whatever(); } catch(Exception e) {}. I saw tons of that in Java. Even a simple file opening can fail for different kind of reasons (the file doesn't exists, it is not readable, on some OS it could be already opened and thus locked). Most of the time, you don't care the reason, but sometimes you want to be more precise. With exceptions, we have an elegant way to manage all failures as a whole, or to differenciate each reason. But you are right, it could be very annoying to write a lot of try/catch blocks. Maybe we could think about something inspired from Lua's protected call function [1]. A convenient mean to say «OK, I know this expression may raise an exception, but I don't care, discard it silently please. I will check if my variable has been set or not.». [1] : http://www.lua.org/pil/8.4.html Personally, I'm used to what other languages like Python do, and I think it makes more sense. Exceptions mean you can try/catch the things your code needs to be prepared for (non-existence, maybe), but other things you haven't considered or are very unlikely, can just not be caught and cause your code to halt execution. And it makes it harder to accidentally avoid checking for errors and then wonder why $file is some NULL or FALSE or other error value. -- Andrew Faulds http://ajf.me/ -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi! Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? Yes, it is. You can control it, unlike the exception which you can not, unless, again, you wrap everything into try/catch on every kind of exception possible. This type of thing is one of the main reasons I like PDO more than MySQLi. In MySQLi I'm constantly checking return values. In PDO I just wrap it all up one try/catch. It's not like if my query fails I'm going to try a different one. Most of the time it's just logging that something went wrong and reporting it upstream somehow. You are using exceptions for normal flow control. It is not what exceptions should be used for. They are called exceptions for a reason. -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi! but sometimes you want to be more precise. With exceptions, we have an elegant way to manage all failures as a whole, or to differenciate each reason. You do not, unless you have 20 exception types and catch them all separately. Which nobody would ever do for one simple reason - what if you miss one? What if next version adds one and you didn't update your code? In practice what happens is people just write try { ...} catch(Exception e) {} and that's it. protected call function [1]. A convenient mean to say «OK, I know this expression may raise an exception, but I don't care, discard it silently please. I will check if my variable has been set or not.». [1] : http://www.lua.org/pil/8.4.html Which, coincidentally, is exactly like PHP works. I see no reason to rewrite all the functions just to add the functions that allow you to go back. -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi! Personally, I'm used to what other languages like Python do, and I think it makes more sense. Exceptions mean you can try/catch the things your code needs to be prepared for (non-existence, maybe), but other things No, they mean you need to *always* try/catch since you have to means to check if the downstream function can throw and exception or maybe call some other function that throws and exception. Exceptions propagate. In Java, you have compiler-controlled throws (which doesn't work in 100% of cases either - I regularly get exception messages from Eclipse, and this one is written by people with great knowledge of Java) - in PHP, you will have nothing. It's one thing when the code writes a warning and returns null when something unexpected happens, another when it throws and exception and you *have* to know which kind it will be and catch it - or just catch everything and ignore it (because you have no idea what it might be) and - check some success value then! you haven't considered or are very unlikely, can just not be caught and cause your code to halt execution. And it makes it harder to accidentally avoid checking for errors and then wonder why $file is some NULL or FALSE or other error value. How it makes it harder? If you forget to check the result, you'll as well forget to try/catch. It just makes the consequences worse - and remember, this all happens in runtime! -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
On 06/08/12 19:48, Stas Malyshev wrote: Hi! Personally, I'm used to what other languages like Python do, and I think it makes more sense. Exceptions mean you can try/catch the things your code needs to be prepared for (non-existence, maybe), but other things No, they mean you need to *always* try/catch since you have to means to check if the downstream function can throw and exception or maybe call some other function that throws and exception. Exceptions propagate. In Java, you have compiler-controlled throws (which doesn't work in 100% of cases either - I regularly get exception messages from Eclipse, and this one is written by people with great knowledge of Java) - in PHP, you will have nothing. It's one thing when the code writes a warning and returns null when something unexpected happens, another when it throws and exception and you *have* to know which kind it will be and catch it - or just catch everything and ignore it (because you have no idea what it might be) and - check some success value then! Why do you have to *always* try/catch? You're making the assumption you need to check for and catch every error. You don't, unless you're working with something like networking. Exceptions mean that an exception, an error that infrequently pops up, but occasionally enough that it matters, can be caught and dealt with. Other ones you don't have to account for, because execution will just stop right there. You don't need to bother checking the return value. you haven't considered or are very unlikely, can just not be caught and cause your code to halt execution. And it makes it harder to accidentally avoid checking for errors and then wonder why $file is some NULL or FALSE or other error value. How it makes it harder? If you forget to check the result, you'll as well forget to try/catch. It just makes the consequences worse - and remember, this all happens in runtime! With exceptions, your code stops running then and there. Without them, with an unchecked return value, your code keeps going until it does something stupid, which can be quite irritating to debug. -- Andrew Faulds http://ajf.me/ -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Am 06.08.2012 20:44, schrieb Stas Malyshev: Hi! but sometimes you want to be more precise. With exceptions, we have an elegant way to manage all failures as a whole, or to differenciate each reason. You do not, unless you have 20 exception types and catch them all separately. No. You just check for those types which you need to handle _here_ and catch-all where apropriate by deriving exceptions from a common library-wide root type. - -- Ralf Lang Linux Consultant / Developer Tel.: +49-170-6381563 Mail: l...@b1-systems.de B1 Systems GmbH Osterfeldstraße 7 / 85088 Vohburg / http://www.b1-systems.de GF: Ralph Dehner / Unternehmenssitz: Vohburg / AG: Ingolstadt,HRB 3537 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.18 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAlAgHIIACgkQCs1dsHJ/X7BSsQCgzbacmum28vsn837bgh1HXmCI tgsAoNicnocgS7gGPoD3WTGflS4ovnXV =+aFB -END PGP SIGNATURE- -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi all, Am 06.08.2012 20:41, schrieb Stas Malyshev: Hi! Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? Yes, it is. You can control it, unlike the exception which you can not, unless, again, you wrap everything into try/catch on every kind of exception possible. Well, if you use return codes, you have to wrap everything in if-statements (maybe more than one, for multiple error codes), so you don't actually gain anything here. If you really need very fine-grained error reporting, you can also use error codes in the exceptions (although you might get a strange mix of both then - I would rather use typed exceptions... I mean, how many functions do you know, where you actually have to deal with 20 different types of errors [without using exceptions for control flow]). You can avoid the mentioned problems with accidentally missing an exception by just using multiple catch blocks: try { // ... } catch (FileNotFoundException $e) { // do something for this exact error message } catch (Exception $e) { // catch all other errors } What I really like when working with exceptions is that you have a natural way of error bubbling. If you have a call stack of about 10 functions and the last one returns null as error value, every of the other 9 functions needs to check for null and return null too (or do something else to hint for an error). If you use exceptions, all this work is done for you, so that you can handle the error on exactly the level, where you want it to be handled. What Andrew also tried to say is, that with some kind of errors you just want the execution of your application to stop (and probably present an error message to the user by using a try-catch around your complete application) and not keep running, just because you forget to check a single return value and the program keeps running in an undefined state. But I guess this boils down to the quite old question: do I want my application to crash (hard) to prevent bugs/corrupt data but create a bad UX for the user; or do I want it to keep running by any means, even if the handled and produced data may be just garbage? In the past, PHP did choose the second alternative (which can be - depending on the case - be both good and bad). Just my thoughts. Cheers, Jannik -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? Yes, it is. You can control it, unlike the exception which you can not, unless, again, you wrap everything into try/catch on every kind of exception possible. This type of thing is one of the main reasons I like PDO more than MySQLi. In MySQLi I'm constantly checking return values. In PDO I just wrap it all up one try/catch. It's not like if my query fails I'm going to try a different one. Most of the time it's just logging that something went wrong and reporting it upstream somehow. You are using exceptions for normal flow control. It is not what exceptions should be used for. They are called exceptions for a reason. It *should* be an exceptional situation if my database queries don't work properly. I've tested my code locally, on a staging environment and sometimes even ran tests on the live server. It is absolutely 100% an exception if something goes wrong, my friend. Opening a file? I have to agree that it should not throw an exception. I was replying more to explain the benefit of exceptions than to refute that one possible use-case. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Levi et al: On Mon, Aug 6, 2012 at 8:55 PM, Levi Morrison morrison.l...@gmail.comwrote: Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? Yes, it is. You can control it, unlike the exception which you can not, unless, again, you wrap everything into try/catch on every kind of exception possible. This type of thing is one of the main reasons I like PDO more than MySQLi. In MySQLi I'm constantly checking return values. In PDO I just wrap it all up one try/catch. It's not like if my query fails I'm going to try a different one. Most of the time it's just logging that something went wrong and reporting it upstream somehow. You are using exceptions for normal flow control. It is not what exceptions should be used for. They are called exceptions for a reason. It *should* be an exceptional situation if my database queries don't work properly. I've tested my code locally, on a staging environment and sometimes even ran tests on the live server. It is absolutely 100% an exception if something goes wrong, my friend. Opening a file? I have to agree that it should not throw an exception. I was replying more to explain the benefit of exceptions than to refute that one possible use-case. It should absolutely throw an exception. If you're opening a file, and the file doesn't exist (in read mode), that's definitely an exceptional circumstance. If it's not, you should be checking for existence first (via file_exists() or is_readable(), etc)... The only situations I consider non-exceptional in terms of PHP errors are those that don't alter the flow via error return. So if fopen errors, you can't just fread the return value. You *need* to change your execution flow based on that error. Therefore, it is exceptional. However, cases where you can logically continue on would not be exceptional. Cases such as substr($string, 100) on a 2 character string, currently raise a warning, but getting an empty string back from it allows you to continue on. The rest of your code won't be effected by the error in a significant way (since the case where the string is 2 characters is the same as if it's 100 characters). So, as a gross overgeneralization, Can I continue on without **having** to check the return value? Yes: Not an exceptional circumstance No: An exceptional circumstance Again, as a gross overgeneralization. Not as a hard rule, but as a quick check... Anthony
Re: [PHP-DEV] Error handling brainstorming
Hi! circumstance. If it's not, you should be checking for existence first (via file_exists() or is_readable(), etc)... This is exactly how we got into this mess with $x = isset($a['x'])?$a['x']:null; We're trying to get out of this mess and you're proposing to build another mess just like that. errors, you can't just fread the return value. You *need* to change your execution flow based on that error. Therefore, it is exceptional. That's exactly what I am saying. Exceptions should not be a means of flow control, and that's exactly what are you doing here. -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
Hi, having worked on the user land side of error handling [1]https://github.com/nicolas-grekas/Patchwork-Logger/blob/master/class/Patchwork/PHP/ErrorHandler.php, I wanted to share some more ideas that could help enhance the current error handling mechanism. Concerning throwing vs not throwing exceptions, the current error handling mechanism allows everyone to code what they prefer, thanks to custom error handling. Personally, I always throw on E_RECOVERABLE_ERROR and E_USER_ERROR. I've found that it's the only safe and compatible choice if I want to reuse some code from others, like a PEAR lib for example, while allowing to recover from situations that otherwise halt script's execution. The really cool thing about error handling in PHP is that we can customize it quite extensively. The bad thing is that we can't customize the behavior for non-catchable errors (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE, E_CORE_WARNING and E_COMPILE_WARNING). Of course, I understand that the PHP engine can't be made to recover from all errors. But my feeling is that some which are currently fatal could be made recoverable [2]https://bugs.php.net/bug.php?id=55428. It would be awesome if as much E_ERROR as possible could be converted to E_RECOVERABLE_ERROR! As a side note for E_PARSE: it is fatal, but only when including and not when inside an eval(). This dual E_PARSE behavior is strange, and I wonder if E_PARSE when including could be made E_RECOVERABLE_ERROR? Then, could also E_PARSE when eval() be made user-catchable? The second idea I wanted to share concerns error silencing. The @ operator can sometimes make debugging a nightmare, especially when the error it hides is one of the non-catchable ones. I know about xdebug.scream, but it works by removing @s, so it makes impossible to differentiate between would be silenced and is not silenced errors and as such it can't be enabled all the time. On my side, to work around silencing, I use a custom error handler [1]https://github.com/nicolas-grekas/Patchwork-Logger/blob/master/class/Patchwork/PHP/ErrorHandler.phpfor catchable errors, and some special code [3] around includes. In my error handler, I use a bit field to configure a set of error levels that are never silenced. The hack [3] for non-catchable errors works, but needs special care. A more general approach would be to add a minimal error reporting level or otherwise named screamed errors bit field in PHP core. Would this be possible? Is it a good idea? Then comes the third idea I wanted to share: to me, the last area where PHP doesn't help debugging is at shutdown time, with the Exception thrown without a stack frame in Unknown on line 0 error. Before shutdown time, uncaught exceptions are transfered to the exception handler (php default or user callback). But at shutdown time, this cryptic error message is always reported instead. I know that shutdown time is very special and code running there should be kept rare, but it happens... So, could we get rid of this cryptic error message, and replace it with the regular exception handling path? I tried and somewhat managed to enhance the situation user land side: if you replace every single call to register_shutdown_function() with [4], and every single __destruct() with [5], then this fixes most of the pb. AFAIK, the only other case where an uncaught exception could be triggered is in a remaining output buffering handler. But as in [4], it wouldn't be hard to encapsulate output buffering handlers in a catching closure. As it looks possible in user land, is the same doable on the engine side? I'm over with my ideas, thanks for reading :) Nicolas [1] https://github.com/nicolas-grekas/Patchwork-Logger/blob/master/class/Patchwork/PHP/ErrorHandler.phphttps://github.com/nicolas-grekas/Patchwork-Logger/blob/master/class/Patchwork/PHP/ErrorHandler.php [2] https://bugs.php.net/bug.php?id=55428https://bugs.php.net/bug.php?id=55428 [3] : ?php $error_level_bak = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); include $file; error_reporting($error_level_bak); ? [4] : ?php function my_register_shutdown_function($callback) { $args = func_get_args(); $callback = function() use ($args) { try { call_user_func_array(array_shift($args), $args); } catch (\Exception $e) { $h = set_exception_handler('var_dump'); // var_dump is never used as per the next line restore_exception_handler(); if (null !== $h) call_user_func($h, $e); else user_error(Uncaught exception ' . get_class($e) . ' in { $e-getFile()} on line {$e-getLine()}, E_USER_WARNING); exit(255); } } return register_shutdown_function($callback); } ? [5] : ?php class foo { function __destruct() { try { // destructor's implementation here } catch (\Exception $e) {
Re: [PHP-DEV] Error handling brainstorming
Hi! Basically Etienne mentioned that the original issue was a good example why would we reconsider throwing exceptions from the core, which is currently discouraged.[2] Stan replied with the idea of turning the current error handling mechanism in php into using Exceptions for everything, but keeping some error types as is/uncatchable. [3] Exceptions are different from PHP errors. For example, if you try to open a file and the file isn't there, throwing exception is a very annoying behavior (yes I know some languages do that, IMO it's wrong). The reason is that it's pretty normal and within normal set of situations to which code should be prepared, so you will either have to obsessively wrap everything with try/catch blocks or do exception typing like Java does. Both options are quite annoying. I think it's much better to just open file and check if the result is OK. Converting it to exception doesn't really improve situation, as if downstream code didn't handle it the upstream probably won't know what to do with that exception either. This leads to code like try { whatever(); } catch(Exception e) {}. I saw tons of that in Java. -- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
. . .For example, if you try to open a file and the file isn't there, throwing exception is a very annoying behavior (yes I know some languages do that, IMO it's wrong). Because checking that the returned variable is `!== FALSE` is *way* better than throwing an exception, right? This type of thing is one of the main reasons I like PDO more than MySQLi. In MySQLi I'm constantly checking return values. In PDO I just wrap it all up one try/catch. It's not like if my query fails I'm going to try a different one. Most of the time it's just logging that something went wrong and reporting it upstream somehow. I understand that opening a file is a bit different than querying a database, but I have to disagree with your entire previous post. Exceptions are much nicer than errors. Of course, everyone is entitled to have and express their own opinion. I'm just sharing mine. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Error handling brainstorming
Hi, We started a discussion about the current error handling mechanism and the possible improvements in the Why do disabled functions / classes generate a WARNING thread[1], but that is a little bit offtopic there, so I decided to create a separate thread for it. Basically Etienne mentioned that the original issue was a good example why would we reconsider throwing exceptions from the core, which is currently discouraged.[2] Stan replied with the idea of turning the current error handling mechanism in php into using Exceptions for everything, but keeping some error types as is/uncatchable. [3] This was brought up on the lists multiple times, we even have two separate RFC with similar idea.[4][5] I tried to explain why I think is impossible to achieve the same functionality by turning the php errors into exceptions without a major overhaul in the engine[6][7], but it seems that I failed to do so. First of all, I would like to clear up the few misunderstandings: Stan: You mentioned that E_STRICT (and E_ERROR but I see no problem with that) should be instant fatal error, I think that was only a typo on your part, could you please clear that up? I would also ask you to confirm that you would like to see every error levels[8] turned into exceptions except the non-recoverable ones. It seems that you and Andrew disagree on that. Andrew: From your mails, it seems that you don't agree with Stan on turning everything but fatals into exceptions[9]. I'm really confused about that, as if we take away warnings (and by that logic everything else which is less serious than a warning) the we would only have the fatal errors (which we already discussed to not turn into exceptions and you also seemed to agree[10]), E_USER and E_RECOVERABLE_ERROR. Is this what you propose? My opinion (and this is what I tried to explain to you) is that it is pretty common in the core and the bundled extensions to raise notices and warnings left and right, and still do something, If we would turn anything less serious than E_RECOVERABLE_ERROR (so any notice, deprecation notice, strict notice or warning)into an exception, that would be a huuge BC break. Basically silecing errors through setting error_reporting level, custom error handlers or the @ operator would stop working, and one should put everything into a try-catch block to not have his code blown into his code constantly. Another thing that I mentioned: even if you catch everything, there would be some things that you couldn't do anymore. Any method which throws notices or strict/deprecated notices or warnings would be broken, as the execution would be halted (as the execution jumps into the catch) which would be a major PITA to the userland developers, and without further work, it could make the userland/engine in a more fragile state, as the original call was interrupted but the execution still continues from a different spot. With the current error handling the execution either resumes after the error handler is called, or the execution is terminates gracefully The current error handling provides a way to trigger multiple errors/warnings for an operation, and allows to still return and continue the execution. Turning everything into exceptions would kill both of those, and without providing something similar suite, we can't do that imo. So basically these are our boundaries: - Fatal errors can't be turned into Exceptions, but it was mentioned multiple times, that there are some fatals, which could be turned into E_RECOVERABLE_ERROR. - Most/all non-fatal errors could be safe to be turned into Exceptions as without explicit measures(try-catch) on the caller's side, it would still stop the execution. - Every other warning/notice/etc. which are just holds additional information but not indicating unsuccessful execution in itself cannot be turned into Exceptions. I have a few ideas about how to proceed from here, but I need some time to gather my thoughts. 1. http://www.mail-archive.com/internals@lists.php.net/msg60043.html 2. http://www.mail-archive.com/internals@lists.php.net/msg60054.html 3. http://www.mail-archive.com/internals@lists.php.net/msg60056.html 4. https://wiki.php.net/rfc/errors_as_exceptions 5. https://wiki.php.net/rfc/enhanced_error_handling 6. http://www.mail-archive.com/internals@lists.php.net/msg60060.html 7. http://www.mail-archive.com/internals@lists.php.net/msg60063.html 8. http://www.php.net/manual/en/errorfunc.constants.php 9. http://www.mail-archive.com/internals@lists.php.net/msg60061.html 10. http://www.mail-archive.com/internals@lists.php.net/msg60065.html -- Ferenc Kovács @Tyr43l - http://tyrael.hu
Re: [PHP-DEV] Error handling brainstorming
On Fri, Aug 3, 2012 at 10:55 PM, Ferenc Kovacs tyr...@gmail.com wrote: Hi, We started a discussion about the current error handling mechanism and the possible improvements in the Why do disabled functions / classes generate a WARNING thread[1], but that is a little bit offtopic there, so I decided to create a separate thread for it. I think there are several types of errors in PHP that have to be handled differently: * There are debugging class errors, like notices etc. They are normally programming mistakes, but don't really prevent further execution of the script. Those should stay as they are. Throwing exceptions here would make things more complicated for the caller. * There are real errors, which should actually stop execution, but which currently don't because throwing a fatal error would be overkill due to it's incatchability (and even recoverable fatals are hard to catch). Many warnings fall into this category. E.g. if a function is called with incorrect parameters (e.g. too little of them) then an E_WARNING is thrown. The wrong function call is clearly an error, but PHP chooses to continue execution there. In my eyes this is a mistake and these cases should be exceptions. (As exceptions are easily catchable one can combine the best of both worlds here). * There is a small number of recoverable fatal errors. Those are obviously the clearest candidates for exceptions, because recoverable fatal *is* basically an exception with very ugly catching. * There are a large number of fatal errors in places which aren't really fatal. They probably should be recoverable fatals now, and as such exceptions in the future. * There is a small number of truly fatal errors, i.e. some kind of problem deep in the engine. There is probably no way to turn those into exceptions. * Another special category are parse and compilations errors. Those are not inherently fatal (e.g. a parse error in an eval() does not have to stop script execution), but they would be really hard to turn into exceptions with the current architecture. To summarize, what I'd like to see: * Not-really fatal errors (and currently recoverable fatal errors) to be converted into exceptions * Some of the warnings be converted to exceptions (depends on the exact context). * Leave notices etc alone. Nikita -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
When I said I'd like to see E_STRICT be fatal/exceptions it wasn't a typo. My choice isn't based as much on what the current error severity is, or what the error severity is supposed to represent in general, because I've found in PHP often the error severity has no connection with the error that's being reported. So I decided this by observing the real-world errors that use a certain severity. Many warnings and all E_STRICT errors clearly point to bugs in the code, wrong method signatures, non-existing variables and constants being used, which can easily do actual data damage if the script keeps running in undefined state (even if the engine is just fine with it). PHP should not split the language semantic into loose, less loose and strict, there should be just one set of semantics: the PHP semantics, and when code does something that doesn't fit, it shouldn't be an ignorable warning. I've found this speeds up the development process, keeps bug count down and protects the site/app's data in case of bugs. Stan -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Error handling brainstorming
On Sat, Aug 4, 2012 at 1:16 AM, Stan Vass sv_for...@fmethod.com wrote: When I said I'd like to see E_STRICT be fatal/exceptions it wasn't a typo. My choice isn't based as much on what the current error severity is, or what the error severity is supposed to represent in general, because I've found in PHP often the error severity has no connection with the error that's being reported. So I decided this by observing the real-world errors that use a certain severity. Many warnings and all E_STRICT errors clearly point to bugs in the code, wrong method signatures, non-existing variables and constants being used, which can easily do actual data damage if the script keeps running in undefined state (even if the engine is just fine with it). are you sure about that? E_STRICT is more about code that works but relying on some quirk or side-effect or simply does a stupid thing. see http://www.mail-archive.com/internals@lists.php.net/msg24665.html about the original proposal and the discussion and you can see the list of E_STRICT errors in the 5.4 branch here: http://lxr.php.net/search?q=E_STRICTdefs=refs=path=%28*c%29+OR+%28*h%29hist=project=PHP_5_4 stuff like using non-existing variables and constants are E_NOTICE, method signature mismatches are either fatal errors or warnings AFAIR. PHP should not split the language semantic into loose, less loose and strict, there should be just one set of semantics: the PHP semantics, and when code does something that doesn't fit, it shouldn't be an ignorable warning. it is the opposite, we allowed sloppy code in the past, and introduced E_STRICT to allow the pedantic people to find and fix the quirks and E_DEPRECATED for finding and migrating the code which will go away. from all of the errors levels only E_DEPRECATED and E_STRICT is what means that atm your code works as intended. but for E_DEPRECATED it will not work in the future, and for E_STRICT it is either does it's job sub optimally or the requested operation is just stupid (but doable). at least this is the theory, if you know something with doesn't in line with this, we could talk about it. :) I've found this speeds up the development process, keeps bug count down and protects the site/app's data in case of bugs. I agree that developing with E_ALL (including E_STRICT) is a good developer mentality. But I would find it too intrusive to start forcing everybody with the next version to either fix every E_STRICT in their code, and even more weird if we do that but still allow them to write code with full of E_WARNING and E_NOTICE and get away with that. -- Ferenc Kovács @Tyr43l - http://tyrael.hu
Re: [PHP-DEV] Error handling brainstorming
On Sat, Aug 4, 2012 at 1:16 AM, Stan Vass sv_for...@fmethod.com wrote: When I said I'd like to see E_STRICT be fatal/exceptions it wasn't a typo. My choice isn't based as much on what the current error severity is, or what the error severity is supposed to represent in general, because I've found in PHP often the error severity has no connection with the error that's being reported. So I decided this by observing the real-world errors that use a certain severity. Many warnings and all E_STRICT errors clearly point to bugs in the code, wrong method signatures, non-existing variables and constants being used, which can easily do actual data damage if the script keeps running in undefined state (even if the engine is just fine with it). are you sure about that? E_STRICT is more about code that works but relying on some quirk or side-effect or simply does a stupid thing. Well think about it. Why is it a goal to let quirky/stide-effect/stupid code run? This almost always ends badly. It also reduces compatibility between code libraries. I.e.: it is the opposite, we allowed sloppy code in the past, and introduced E_STRICT to allow the pedantic people to find and fix the quirks and E_DEPRECATED for finding and migrating the code which will go away. If you use a well tested, popular library by sloppy coders who don't mind E_STRICT and E_NOTICE, but you're pedantic, what happens? You have to live with your error log filled with noise from the library or fork the library. And when the sloppy coders miss bugs because they've decided the real PHP is about sloppy code that still works somehow, they miss bugs and then blame themselves or PHP for being a language that allows buggy code. This is the end result if trying to turn PHP into everything for everybody. Instead, PHP should make up it's mind and stop littering the php.ini with semantics/behavior configuration for the language. Have one behavior. Stick with it. Make it obvious.
Re: [PHP-DEV] Error handling brainstorming
On Sat, Aug 4, 2012 at 1:44 AM, Stan Vass sv_for...@fmethod.com wrote: ** On Sat, Aug 4, 2012 at 1:16 AM, Stan Vass sv_for...@fmethod.com wrote: When I said I'd like to see E_STRICT be fatal/exceptions it wasn't a typo. My choice isn't based as much on what the current error severity is, or what the error severity is supposed to represent in general, because I've found in PHP often the error severity has no connection with the error that's being reported. So I decided this by observing the real-world errors that use a certain severity. Many warnings and all E_STRICT errors clearly point to bugs in the code, wrong method signatures, non-existing variables and constants being used, which can easily do actual data damage if the script keeps running in undefined state (even if the engine is just fine with it). are you sure about that? E_STRICT is more about code that works but relying on some quirk or side-effect or simply does a stupid thing. Well think about it. Why is it a goal to let quirky/stide-effect/stupid code run? This almost always ends badly. It also reduces compatibility between code libraries. I.e.: my words aren't getting through to you. it is the opposite, we allowed sloppy code in the past, and introduced E_STRICT to allow the pedantic people to find and fix the quirks and E_DEPRECATED for finding and migrating the code which will go away. If you use a well tested, popular library by sloppy coders who don't mind E_STRICT and E_NOTICE, but you're pedantic, what happens? You have to live with your error log filled with noise from the library or fork the library. And when the sloppy coders miss bugs because they've decided the real PHP is about sloppy code that still works somehow, they miss bugs and then blame themselves or PHP for being a language that allows buggy code. This is the end result if trying to turn PHP into everything for everybody. Instead, PHP should make up it's mind and stop littering the php.ini with semantics/behavior configuration for the language. Have one behavior. Stick with it. Make it obvious. if we turn E_STRICT to behave exactly as E_ERROR there is no point keeping the E_STRICT level. personally I disagree with turning something which was a pedantic notice in one version into an unsupported feature which fatals out if you try to use it in the next. maybe E_STRICT-E_DEPRECATED-E_ERROR -- Ferenc Kovács @Tyr43l - http://tyrael.hu
Re: [PHP-DEV] Error handling brainstorming
if we turn E_STRICT to behave exactly as E_ERROR there is no point keeping the E_STRICT level. personally I disagree with turning something which was a pedantic notice in one version into an unsupported feature which fatals out if you try to use it in the next. maybe E_STRICT-E_DEPRECATED-E_ERROR I do think there's no point keeping the E_STRICT level. In fact, there's no point keeping any level except - E_WARNING (strictly for developer tips like deprecated functionality, and not for say division by zero errors or Stream I/O errors like it is today); - E_ERROR (everything that's not a developer tip but an error, should be this type, not a notice/warning/strict); - E_FATAL_ERROR (direct script halt). That's just how I see it. Today we have these instead: - E_ERROR - E_WARNING - E_PARSE - E_NOTICE - E_CORE_ERROR - E_CORE_WARNING - E_COMPILE_ERROR - E_COMPILE_WARNING - E_USER_ERROR - E_USER_WARNING - E_USE_NOTICE - E_STRICT - E_RECOVERABLE_ERROR - E_DEPRECATED - E_USER_DEPRECATED Most of those have no reason to exist and especially they have no reason to be exposed as different severities at the user level. It seems like the severity levels have become a poor man's error *type* codes, which are needed, and at much more granular level, but as this is a severity, that's not the place to differentiate them. I never spoke about E_STRICT going fatal in the next version of PHP. I'm saying this in the context of my advice about using an error handler. I do this in my error handler (not just development, but also production), but still I think it could be a nice long-term goal to cleaning up PHP. Stan