[RFC] Exceptions in the engine

php.internals

Nikita Popov

12 years ago
Hi internals! I'd like to propose an RFC, which allows the use of exceptions within the engine and also allows changing existing fatal errors to exceptions: https://wiki.php.net/rfc/engine_exceptions This topic has been cropping up in the discussions for several of the recent RFCs and I think the time has come to consider moving away from fatal errors. Thoughts? Thanks, Nikita

Johannes Schlueter

12 years ago
On Thu, 2013-10-24 at 19:41 +0200, Nikita Popov wrote:
> Hi internals! > > I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions:
If there is a way to recover from a fatal error it shouldn't be E_ERROR but E_RECOVERABLE. Catching E_RECOVERABLE is a pita. this should be replaced by exceptions imo. E_FATAL should stay for things where it is too much trouble to recover as the engine is in undefined state. johannes

Adam Harvey

12 years ago
On 24 October 2013 10:41, Nikita Popov <nikita.ppv@gmail.com> wrote:
> I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts?
I love the idea — unified error and exception handling would be a huge win both for simplifying code bases and teaching new developers — but I don't see any possible way we could do this in a 5.x release. The BC issues are just too great, and too many people rely heavily on the set_error_handler() behaviour that we have today. A couple of specific points that jumped at out me on my first skim: 1. I know Python has BaseException, but it feels a little like the exception version of functions with the name "real" in them. :) If this was $next_major material, then we could probably look at keeping Exception as the top level and inserting a UserException under it that userland exceptions derive from. (Or just not do it at all.) 2. Again, if this is $next_major material, I wouldn't selectively convert errors to exceptions as the "policy changes" section suggests — let's do them all and be done with it, and the only things that would still be errors are genuinely uncatchable things that already can't be handled by set_error_handler(). There's probably a broader discussion here around whether we should be starting to think about a new major release and what that would look like, but that's definitely not for this thread! Adam

Rowan Collins

12 years ago
On 24/10/2013 19:01, Adam Harvey wrote:
> On 24 October 2013 10:41, Nikita Popov <nikita.ppv@gmail.com> wrote: >> I'd like to propose an RFC, which allows the use of exceptions within the >> engine and also allows changing existing fatal errors to exceptions > I love the idea — unified error and exception handling would be a huge > win both for simplifying code bases and teaching new developers — but > I don't see any possible way we could do this in a 5.x release. The BC > issues are just too great, and too many people rely heavily on the > set_error_handler() behaviour that we have today.
FWIW, as an outsider, I'd tend to agree with this. It might be possible to implement this in a backwards compatible way, but there would be a lot of details to consider. More importantly, if this isn't a big enough change to warrant a major release, what is? The more major features make it into 5.x, with BC carefully maintained, the more it feels like 5.x will go on living indefinitely, with the implication - according to the current release process - that deprecated or broken APIs will "never" be removed or fixed.
> I wouldn't selectively convert errors to exceptions as the "policy changes" section suggests > — let's do them all and be done with it
This I agree with even more strongly, but I also don't think this should be a one-to-one mapping of the existing errors. From what I can see, the current patch uses neither sub-classes nor exception codes, just the existing message strings. This seems like a massive missed opportunity - a big part of exception handling is choosing which exceptions to handle, and at the moment, the only way to detect what error was thrown is by string matching, including accounting for substituted parts. It would also be nice to consider changing the handling of non-fatals as well, although I'm not quite sure how they should work. Again, there is currently no way to detect the "type" of a warning or notice, only its severity; nor is there an easy way to have different handlers for different severities. Those severities can also be pretty arbitrary: e.g. an undefined constant issues an E_NOTICE, but a class constant is E_ERROR, presumably for historical reasons, which would matter less if there were additional meta-data to recognise them by. The other rather more blue-sky thought I had is that it would be nice to scope error-handling "lexically", in the sense of all functions in a particular included library being under a different error-handling regime from the outer program, reagardless of execution order. There are old modules in PEAR which work fine with current versions of PHP, but emit lots of E_DEPRECATED or E_NOTICE messages; what I really want to say is "yes, our use of that whole module is deprecated, we're not going to clean it up, but our own code should be nice and clean". Regards,
-- Rowan Collins [IMSoP]

Nikita Popov

12 years ago
On Thu, Oct 24, 2013 at 8:01 PM, Adam Harvey <aharvey@php.net> wrote:
> On 24 October 2013 10:41, Nikita Popov <nikita.ppv@gmail.com> wrote: > > I'd like to propose an RFC, which allows the use of exceptions within the > > engine and also allows changing existing fatal errors to exceptions: > > > > https://wiki.php.net/rfc/engine_exceptions > > > > This topic has been cropping up in the discussions for several of the > > recent RFCs and I think the time has come to consider moving away from > > fatal errors. > > I love the idea — unified error and exception handling would be a huge > win both for simplifying code bases and teaching new developers — but > I don't see any possible way we could do this in a 5.x release. The BC > issues are just too great, and too many people rely heavily on the > set_error_handler() behaviour that we have today. >
Reading through the mails in this thread a lot of people seem to have concerns about backwards compatibility. I can see where this comes from, "switch to using exceptions" certainly sounds like a seriously big BC break - but I don't think it actually is. Let's start by considering only E_ERROR (and leave recoverable fatals for later): First of all we should establish that fatal errors do not occur during normal program execution. If you take your PHP 5.5 program and run it on PHP 5.6 (with E_ERROR converted to exceptions) you will see *absolutely no difference*. If you do, that means your code was previously throwing a fatal error already, i.e. it didn't actually work in the first place. Let me say this again, because I think it's important: If your code was working previously, it will continue working the same way after converting fatals to exceptions. But what happens when the program has a bug and does throw a fatal error? In this case the program already doesn't work, so what changes isn't particularly critical, but we should still consider it. There are basically two things that might happen: 1. Most likely everything will work just as you expect, the error will only be presented differently. Either because the exception is not handled and the message changes because of that (with stack trace) or an exception-handler or top-level catch-block handles it rather than the shutdown function and presents it in some different way. In either case this shouldn't matter - I certainly do hope that changing the look of an error is not considered a compatibility break... 2. A misplaced catch-and-ignore block catches the fatal error and dismisses it. This is of course unfortunate, but it's really not more than that. It's an inconvenience, yes, but it does not actually break anything. Some people have mentioned something about code-paths becoming reachable that were previous not, but I don't see how that applies. If you used a try/catch block, then you already expect that the code-path in the catch or the code after it may be taken. At this point I'd also like to point out that if code contains a catch-all block, it likely is also supposed to catch-all, so hiding the error is likely not even wrong. PHP never did Java's mistake of introducing checked exceptions, so PHP does not have a widespread pattern of "wrap everything with catch(Exception $e) to silence the compiler". So, that much on fatal errors. What about E_RECOVERABLE_ERROR? Here there may actually be BC issues. As already mentioned, recoverable fatals can currently be ignored with a custom error handler and exceptions make that impossible. So it might be that someone wrote an application that throws recoverable errors during "normal" program execution. I don't think that this is particularly realistic and as such I don't think this is really problematic, but others might see this differently. If that is the case it might become necessary to keep recoverable fatal errors as is. In conclusion, I don't see any non-negligible BC issues for the fatal-error change and only minor BC issues for the recoverable-fatal change (and even that can be dropped). As such I don't think pushing this off to PHP 6 is justified. I'd also like to point out that this RFC is a blocker for some of my other proposals. In particular, I don't think that I can in good conscience move the named arguments and argument unpacking RFCs forward without the ability to use exceptions. I would really hate to move named args off to PHP 6. Thanks, Nikita

Alexey Zakhlestin

12 years ago
On 27 окт. 2013 г., at 1:40, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Reading through the mails in this thread a lot of people seem to have > concerns about backwards compatibility. I can see where this comes from, > "switch to using exceptions" certainly sounds like a seriously big BC break > - but I don't think it actually is. > > Let's start by considering only E_ERROR (and leave recoverable fatals for > later):
+1
> First of all we should establish that fatal errors do not occur during > normal program execution. If you take your PHP 5.5 program and run it on > PHP 5.6 (with E_ERROR converted to exceptions) you will see *absolutely no > difference*. If you do, that means your code was previously throwing a > fatal error already, i.e. it didn't actually work in the first place. Let > me say this again, because I think it's important: If your code was working > previously, it will continue working the same way after converting fatals > to exceptions. > > But what happens when the program has a bug and does throw a fatal error? > In this case the program already doesn't work, so what changes isn't > particularly critical, but we should still consider it. There are basically > two things that might happen: > > 1. Most likely everything will work just as you expect, the error will only > be presented differently. Either because the exception is not handled and > the message changes because of that (with stack trace) or an > exception-handler or top-level catch-block handles it rather than the > shutdown function and presents it in some different way. In either case > this shouldn't matter - I certainly do hope that changing the look of an > error is not considered a compatibility break... > 2. A misplaced catch-and-ignore block catches the fatal error and dismisses > it. This is of course unfortunate, but it's really not more than that. It's > an inconvenience, yes, but it does not actually break anything. Some people > have mentioned something about code-paths becoming reachable that were > previous not, but I don't see how that applies. If you used a try/catch > block, then you already expect that the code-path in the catch or the code > after it may be taken. At this point I'd also like to point out that if > code contains a catch-all block, it likely is also supposed to catch-all, > so hiding the error is likely not even wrong. PHP never did Java's mistake > of introducing checked exceptions, so PHP does not have a widespread > pattern of "wrap everything with catch(Exception $e) to silence the > compiler".
I think it is a good idea to avoid #2 altogether by introducing BaseException and using separate hierarchy for ex-fatal errors. old code will ignore new exceptions and those will fall thru down to generic exception-handler and shutdown-handler New code will be able to use `catch (BaseException $e)` but that should be deliberate decision by code-author
> So, that much on fatal errors. What about E_RECOVERABLE_ERROR? > > Here there may actually be BC issues. As already mentioned, recoverable > fatals can currently be ignored with a custom error handler and exceptions > make that impossible. So it might be that someone wrote an application that > throws recoverable errors during "normal" program execution. I don't think > that this is particularly realistic and as such I don't think this is > really problematic, but others might see this differently. If that is the > case it might become necessary to keep recoverable fatal errors as is. > > In conclusion, I don't see any non-negligible BC issues for the fatal-error > change and only minor BC issues for the recoverable-fatal change (and even > that can be dropped). As such I don't think pushing this off to PHP 6 is > justified. I'd also like to point out that this RFC is a blocker for some > of my other proposals. In particular, I don't think that I can in good > conscience move the named arguments and argument unpacking RFCs forward > without the ability to use exceptions. I would really hate to move named > args off to PHP 6.
I think “safe" set of changes (E_ERROR + separate exceptions-hierarchy) should be implemented in 5.6. Everything else should be planned for 6.x
-- Alexey Zakhlestin CTO at Grids.by/you https://github.com/indeyets PGP key: http://indeyets.ru/alexey.zakhlestin.pgp.asc

Rowan Collins

12 years ago
On 26/10/2013 22:40, Nikita Popov wrote:
> Reading through the mails in this thread a lot of people seem to have > concerns about backwards compatibility. I can see where this comes from, > "switch to using exceptions" certainly sounds like a seriously big BC break > - but I don't think it actually is.
As I understand it, the current release process doesn't say anything about "big" or "major" BC breaks, but that minor releases should not break BC *at all*. There may be justification for relaxing that rule, but the justification needs to be made.
> First of all we should establish that fatal errors do not occur during > normal program execution. If you take your PHP 5.5 program and run it on > PHP 5.6 (with E_ERROR converted to exceptions) you will see *absolutely no > difference*. If you do, that means your code was previously throwing a > fatal error already, i.e. it didn't actually work in the first place.
There's a subtlety here that could be important - a script that causes fatal errors *in some situations* could still work in other situations. This is not like allowing previously invalid syntax, where an entire file would previously have failed to compile, these are fundamentally run-time behaviours, even if they *should* never happen.
> A misplaced catch-and-ignore block catches the fatal error and dismisses > it. This is of course unfortunate, but it's really not more than that. It's > an inconvenience, yes, but it does not actually break anything. Some people > have mentioned something about code-paths becoming reachable that were > previous not, but I don't see how that applies. If you used a try/catch > block, then you already expect that the code-path in the catch or the code > after it may be taken.
I think the comment you're referring to was mine [http://php.markmail.org/message/n3aw4kqhclwvpsvs] so I'll expand on it a little. Ignoring catch-all blocks, to which BaseException is a trivial solution/workaround, part of the stated advantage of this change is that finally blocks and destructors will run if a fatal error occurs. That means that code is running in an application state which was previously impossible (except for in the very limited case of the shutdown handler). For instance, if a mis-configured deployment meant that a particular class could not be autoloaded, that would previously have halted all code as soon as an attempt was made to use it. With an exception model, however, finally blocks and destructors, which might themselves rely on that class in some subtle way, would attempt to run. Hopefully, this wouldn't cause anything other than a pile of further errors - it might even transparently increase robustness - but it's not impossible to imagine a situation where such an application state would corrupt data or expose a security flaw. I don't know whether to consider this a "major" or "serious" change in behaviour, let alone whether it would generally be "good" or "bad", but it is a change in behaviour.
> PHP never did Java's mistake of introducing checked exceptions, so PHP does not have a widespread > pattern of "wrap everything with catch(Exception $e) to silence the compiler".
Actually, I would have thought checked exceptions would make catch-alls *less* likely, because you know for sure which exceptions need to be handled. In PHP, you can't rely on lower-level exceptions having been handled or wrapped up by libraries, so there's a possibility of e.g. a PDO_Exception cropping up in the middle of your business logic. But that's really beside the point I think - people can use catch(Exception) for whatever they like, and speculation about how many people will be affected by a BC break is not the same as understanding what the BC break is.
> As such I don't think pushing this off to PHP 6 is justified.
It feels like there's an assumption here that PHP 6 is a long way away. Rather than seeing it as pushing this feature away, it could be seen as pulling a major release closer. See e.g. Ferenc's suggestion to create separate branches for next-minor and next-major: http://php.markmail.org/message/v4gzpnfn7x6xonjs The other question is, what's the hurry? If this is introduced piecemeal, the result is an even more fragmented error-handling model, with a few slightly improved features, some of the time. And then when a plan is put together to overhaul error handling in general, the way EngineExceptions work will have to be worked into the plan, whether they fit or not, or a second "not very serious" BC break will be needed.
> I'd also like to point out that this RFC is a blocker for some > of my other proposals. In particular, I don't think that I can in good > conscience move the named arguments and argument unpacking RFCs forward > without the ability to use exceptions.
I'm not sure why those would particularly need exception handling any more than existing language features (is calling a function with a non-existent named parameter that different from calling a non-existent function?) but that's probably been discussed elsewhere. I would be interested to know though, hypothetically, if PHP did not have exceptions at all, do you think you'd feel it couldn't have named arguments until they were added?
-- Rowan Collins [IMSoP]

Nikita Popov

12 years ago
On Sun, Oct 27, 2013 at 2:47 PM, Rowan Collins <rowan.collins@gmail.com>wrote:
> On 26/10/2013 22:40, Nikita Popov wrote: > >> Reading through the mails in this thread a lot of people seem to have >> concerns about backwards compatibility. I can see where this comes from, >> "switch to using exceptions" certainly sounds like a seriously big BC >> break >> - but I don't think it actually is. >> > > As I understand it, the current release process doesn't say anything about > "big" or "major" BC breaks, but that minor releases should not break BC *at > all*. There may be justification for relaxing that rule, but the > justification needs to be made.
That's a misphrasing on behalf of the RFC. The question is always "how big is the break?" not "is there a break?". The latter question doesn't even make sense because any change to PHP - including the most trivial bugfixes - breaks compatibility to *some* degree (well, unless the change is "fix whitespace in foo.c") Obligatory XKCD: http://xkcd.com/1172/
> > First of all we should establish that fatal errors do not occur during >> normal program execution. If you take your PHP 5.5 program and run it on >> PHP 5.6 (with E_ERROR converted to exceptions) you will see *absolutely no >> difference*. If you do, that means your code was previously throwing a >> fatal error already, i.e. it didn't actually work in the first place. >> > > There's a subtlety here that could be important - a script that causes > fatal errors *in some situations* could still work in other situations. > This is not like allowing previously invalid syntax, where an entire file > would previously have failed to compile, these are fundamentally run-time > behaviours, even if they *should* never happen.
My point here was that you can only see a change in cases where the program already doesn't work correctly. If your code ran fine beforehand, it will continue to do so. Imho that's the most important bit as far as compatibility is concerned (to keep working code working). I think the comment you're referring to was mine [
> http://php.markmail.org/message/n3aw4kqhclwvpsvs] so I'll expand on it a > little. > > Ignoring catch-all blocks, to which BaseException is a trivial > solution/workaround, part of the stated advantage of this change is that > finally blocks and destructors will run if a fatal error occurs. That means > that code is running in an application state which was previously > impossible (except for in the very limited case of the shutdown handler). > > For instance, if a mis-configured deployment meant that a particular class > could not be autoloaded, that would previously have halted all code as soon > as an attempt was made to use it. With an exception model, however, finally > blocks and destructors, which might themselves rely on that class in some > subtle way, would attempt to run. Hopefully, this wouldn't cause anything > other than a pile of further errors - it might even transparently increase > robustness - but it's not impossible to imagine a situation where such an > application state would corrupt data or expose a security flaw. > > I don't know whether to consider this a "major" or "serious" change in > behaviour, let alone whether it would generally be "good" or "bad", but it > is a change in behaviour.
Yes, of course behavior changes in some way - that's kind of stating the obvious. I wouldn't be writing an RFC if I just wanted to keep everything exactly as is. See the first paragraph again: Knowing that there is a change doesn't help us at all (because its there by definition), the only interesting question is how severe it is. Maybe some context will help here: We already changed the behavior of destructors in relation to fatal errors once - and that was during a bugfix release :)
> As such I don't think pushing this off to PHP 6 is justified. >> > > It feels like there's an assumption here that PHP 6 is a long way away. > Rather than seeing it as pushing this feature away, it could be seen as > pulling a major release closer. See e.g. Ferenc's suggestion to create > separate branches for next-minor and next-major: http://php.markmail.org/* > *message/v4gzpnfn7x6xonjs<http://php.markmail.org/message/v4gzpnfn7x6xonjs> >
Yes, my comments are under the assumption that PHP 6 won't be there anytime soon. Of course, if people suddenly decide that PHP 5.6 should really be PHP 6, then there would be little to argue about ^^ Unless we have *concrete* plans regarding PHP 6 saying "this should go into (a hypothetical, non-existing) PHP 6" is roughly equivalent to just declining the feature. PHP 6 only makes sense to me if we're planning to actually do changes with major BC impact. Not things like this RFC, but changes of basic language semantics (like fixing the 0 == "foo" comparison and other foundational issues).
> > I'd also like to point out that this RFC is a blocker for some >> of my other proposals. In particular, I don't think that I can in good >> conscience move the named arguments and argument unpacking RFCs forward >> without the ability to use exceptions. >> > > I'm not sure why those would particularly need exception handling any more > than existing language features (is calling a function with a non-existent > named parameter that different from calling a non-existent function?) but > that's probably been discussed elsewhere. I would be interested to know > though, hypothetically, if PHP did not have exceptions at all, do you think > you'd feel it couldn't have named arguments until they were added? >
Especially the named arguments RFC introduces a very big slurry of (completely inappropriate) warnings. I don't like that and would much prefer to properly handle things. Of course, many people don't really care about error conditions, so I might continue those proposals even without exceptions, but I'm not really sure about that. Nikita

Pierre Joye

12 years ago
On Sun, Oct 27, 2013 at 4:51 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Yes, my comments are under the assumption that PHP 6 won't be there anytime > soon. Of course, if people suddenly decide that PHP 5.6 should really be > PHP 6,
Really not. As of now, we have enough materials for a 5.6 and a 6.x development will most likely take 1-2 years (no, we won't let it go over many years). But 6.x discussions are a bit off topic, except about when should we allow general exceptions usage in the core :)
> then there would be little to argue about ^^ Unless we have > *concrete* plans regarding PHP 6 saying "this should go into (a > hypothetical, non-existing) PHP 6" is roughly equivalent to just declining > the feature. > > PHP 6 only makes sense to me if we're planning to actually do changes with > major BC impact. Not things like this RFC, but changes of basic language > semantics (like fixing the 0 == "foo" comparison and other foundational > issues).
I disagree here, with both your comment about the relevance of this RFC and what should be a 6.0. I like the idea to move to exception, optionally. But I do not like the idea to have them in one single place, and do not allow them in extensions or other part of the engine. Moving to exceptions usage in the core should be well designed and planed, and globally. This will be something much harder and longer to do than what is proposed here. Cheers,
-- Pierre @pierrejoye | http://www.libgd.org

Rowan Collins

12 years ago
On 27/10/2013 15:51, Nikita Popov wrote:
> Unless we have *concrete* plans regarding PHP 6 saying "this should go > into (a hypothetical, non-existing) PHP 6" is roughly equivalent to > just declining the feature.
I agree with that, and think it is a real problem, but there are two solutions: abandon the BC rules for 5.x releases, or make some concrete plans for 6.x. Otherwise, the release process might as well not distinguish minor and major releases at all, and just define what is and isn't allowed in terms of BC for the foreseeable future of PHP.
> PHP 6 only makes sense to me if we're planning to actually do changes > with major BC impact. Not things like this RFC, but changes of basic > language semantics (like fixing the 0 == "foo" comparison and other > foundational issues).
Not every major release has to fix everything. An overhaul of error handling, in general, would seem like a good Big Feature to pin a major release on, just as Unicode strings would have been, had it gone ahead.
-- Rowan Collins [IMSoP]

Pierre Joye

12 years ago
On Sun, Oct 27, 2013 at 5:11 PM, Rowan Collins <rowan.collins@gmail.com> wrote:
> On 27/10/2013 15:51, Nikita Popov wrote: > >> Unless we have *concrete* plans regarding PHP 6 saying "this should go >> into (a hypothetical, non-existing) PHP 6" is roughly equivalent to just >> declining the feature.
Not sure where Nikita posted that, so I will comment here :) No, it is about defining what is good in 5.x and what is good for a future 6.x. Also the 6.x discussion should be taken in a separate thread. But I won't suggest to do it now, let keep us focused on getting 5.6 out in time > decide what goes in 5.6.
> I agree with that, and think it is a real problem, but there are two > solutions: abandon the BC rules for 5.x releases, or make some concrete > plans for 6.x.
It is not the time now to make plan for 6.x. But to decide what goes in 5.6 or not.
> Otherwise, the release process might as well not distinguish minor and major > releases at all, and just define what is and isn't allowed in terms of BC > for the foreseeable future of PHP.
That's what it does, both parts. And we can develop a 6.x branch in parallel to 5.x, f.e. 5.6.x and 5.7. The key here is to decide what are the key big changes we want in (tsrm drop, TLS support, general exceptions usage could be some of them). Cheers.
-- Pierre @pierrejoye | http://www.libgd.org

Rowan Collins

12 years ago
On 27/10/2013 19:08, Pierre Joye wrote:
> It is not the time now to make plan for 6.x. But to decide what goes > in 5.6 or not.
I don't think the two can be completely separated. If there were plans for over-hauling error handling in 6.x, those plans could affect decisions in 5.6; if there is definitely no will for such an over-haul, or for 6.x even existing in the foreseeable future, that makes small changes in 5.6 more attractive.
-- Rowan Collins [IMSoP]

Rowan Collins

12 years ago
On 27/10/2013 15:51, Nikita Popov wrote:
> The question is always "how big is the break?" not "is there a > break?". The latter question doesn't even make sense because any > change to PHP - including the most trivial bugfixes - breaks > compatibility to *some* degree (well, unless the change is "fix > whitespace in foo.c") Obligatory XKCD: http://xkcd.com/1172/
A fair point, and trust Randall to be the one to capture its essence. I guess the question then is, if the changes are so minor, are the benefits actually any bigger than the drawbacks? As part of a move towards changing error handling in general, it's a good idea, but that implies it is the first milestone in some larger plan, which doesn't seem to be the case as yet.
-- Rowan Collins [IMSoP]

Joe Watkins

12 years ago
On 10/24/2013 06:41 PM, Nikita Popov wrote:
> Hi internals! > > I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts? > > Thanks, > Nikita >
Delicious, obviously ... I will add that; if we are going to push forward with using exceptions properly, then there's internal code throwing base Exceptions objects and that needs to be fixed, catch(Exception $ex) will have _even less meaning_ than it does today if we are to throw exceptions in place of fatal errors. I have to ask the question; why stop at half way ?? A warning does absolutely nothing for the programmer, or their code, all it does is warn the client, who isn't very likely to even be in contact with the programmer, even less likely has access to their code. Take the following code: $handle = fopen("/path/to/file", "w+"); if ($handle) { } If there is no $handle, I have no idea why, god only knows what the logic looks like to detect why the failure occurred, and it doesn't have to be fopen, can be almost anything that doesn't throw exceptions. So, even though, some previously called function or method almost certainly has some information that is useful, I have to make more sys or library calls to determine the nature of the error and the code path to take. try { $handle = fopen ("/path/to/file", "w+"); } catch (FileNotFoundException $fnf) { } catch (PermissionException $pex) { } catch (DiskFullException $dfe) { } [Note: the names of the exceptions and functions used _do not matter_, consider the pattern only] This solution has existed for years, why do we shy away from it so much ?? I've never heard a really good argument for the existence of warnings or notices at all. This is all said with the knowledge that some errors are truly fatal, there is no point to, or chance of, throwing an exception. +1 on the whole idea, however far we are able to take it ... the further the better in my opinion ... Cheers Joe

Nikita Popov

12 years ago
On Thu, Oct 24, 2013 at 9:27 PM, Joe Watkins <krakjoe@php.net> wrote:
> I have to ask the question; why stop at half way ?? > > A warning does absolutely nothing for the programmer, or their code, all > it does is warn the client, who isn't very likely to even be in contact > with the programmer, even less likely has access to their code. > > [...] > > This solution has existed for years, why do we shy away from it so much ?? > I've never heard a really good argument for the existence of warnings or > notices at all. > > This is all said with the knowledge that some errors are truly fatal, > there is no point to, or chance of, throwing an exception. > > +1 on the whole idea, however far we are able to take it ... the further > the better in my opinion ... >
Changing existing warnings to exceptions would be a (massive) compatibility break. Changing fatal errors isn't (in first order approximation) because - well, they are fatal, you can't really depend on their behavior unless you are using them as a die-substitute or something ^^ As this RFC is aimed at the 5.x branch it needs to maintain BC to a reasonable level, so changing warnings is really out of its scope. If you want to change warnings to exceptions that should be a separate proposal targeted at PHP 6. I'd prefer to keep it out of this thread. Thanks, Nikita

Joe Watkins

12 years ago
Okay that's reasonable enough ... Baby steps :) Cheers Joe On 24 Oct 2013 20:40, "Nikita Popov" <nikita.ppv@gmail.com> wrote:

Pierre Joye

12 years ago
On Thu, Oct 24, 2013 at 7:41 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals! > > I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts?
I like the idea, well done! I understand that this RFC refers to the engine only, however I think many exts may follow this path too. We should consider about naming conventions for the extensions as well. Another point, I'm wondering if 5.x is the right time to introduce exceptions in core.
-- Pierre @pierrejoye | http://www.libgd.org

Andrew Faulds

12 years ago
On 24/10/2013 18:41, Nikita Popov wrote:
> Hi internals! > > I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts? > > Thanks, > Nikita >
I love this proposal! Errors are a very dated way of handling errors, and there are a lot of fatal errors which are unnecessarily fatal. This would mean many could stop being fatal and start being exceptions, which is great news.
-- Andrea Faulds http://ajf.me/

Stas Malyshev

12 years ago
Hi! Looking at the patch, it converts zend_error_noreturn into ZEND_IMPOSSIBLE, which is nothing in non-debug mode. This means code that expected that execution ceases it this point (and jumps to a safe bail-out point) now just continues in non-debug mode (probably causing crash or memory corruption) or exits the process on failed assert in debug mode. I'm not sure it is a good idea to do this. A lot of code assumes execution does not proceed past E_ERROR, but exceptions do not work that way.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Nikita Popov

12 years ago
On Thu, Oct 24, 2013 at 9:57 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
> Hi! > > Looking at the patch, it converts zend_error_noreturn into > ZEND_IMPOSSIBLE, which is nothing in non-debug mode. This means code > that expected that execution ceases it this point (and jumps to a safe > bail-out point) now just continues in non-debug mode (probably causing > crash or memory corruption) or exits the process on failed assert in > debug mode. I'm not sure it is a good idea to do this.
To make sure that there are no misunderstandings, Stas is referring to two particular occurrences where E_ERROR has been replaced with a ZEND_IMPOSSIBLE macro. Both occurrences are unreachable code (or so I judged), so they are effectively assertions implemented using E_ERROR rather than assert(). The ZEND_IMPOSSIBLE macro is a more explicit way of saying assert(0). PHP removes assertions in non-debug builds (optimization), so this follows suit. I did not mention this in the RFC because I'm not yet sure this change is necessary and I might yet keep them as (pointless) fatal errors instead, just in case. This is mainly a note to myself that I looked at the error and decided that it does not require conversion.
> A lot of code assumes execution does not proceed past E_ERROR, but
exceptions do not work that way.
>
That's correct. In the places where I replaced fatal errors with exceptions I make sure to free resources and handle the exception. Nikita

Larry Garfield

12 years ago
On 10/24/13 12:41 PM, Nikita Popov wrote:
> Hi internals! > > I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts? > > Thanks, > Nikita
As a PHP user-space developer I love this idea. However, I share the concern of others here that it could result in BC unpleasantness, even if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't know off hand how various versions of Drupal would handle this. --Larry Garfield

Joe Watkins

12 years ago
On 10/24/2013 11:31 PM, Larry Garfield wrote:
> On 10/24/13 12:41 PM, Nikita Popov wrote: >> Hi internals! >> >> I'd like to propose an RFC, which allows the use of exceptions within the >> engine and also allows changing existing fatal errors to exceptions: >> >> https://wiki.php.net/rfc/engine_exceptions >> >> This topic has been cropping up in the discussions for several of the >> recent RFCs and I think the time has come to consider moving away from >> fatal errors. >> >> Thoughts? >> >> Thanks, >> Nikita > > As a PHP user-space developer I love this idea. However, I share the > concern of others here that it could result in BC unpleasantness, even > if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't > know off hand how various versions of Drupal would handle this. > > --Larry Garfield
How could anything be reliant on the behaviour of a fatal error in any meaningful way ?? Cheers Joe

Richard Bradley

12 years ago
> -----Original Message----- > From: Joe Watkins [mailto:krakjoe@php.net] > Sent: 25 October 2013 14:02 > To: internals@lists.php.net; Larry Garfield > Subject: Re: [PHP-DEV] [RFC] Exceptions in the engine > > On 10/24/2013 11:31 PM, Larry Garfield wrote: > > On 10/24/13 12:41 PM, Nikita Popov wrote: > >> Hi internals! > >> > >> I'd like to propose an RFC, which allows the use of exceptions within > >> the engine and also allows changing existing fatal errors to exceptions: > >> > >> https://wiki.php.net/rfc/engine_exceptions > >> > >> This topic has been cropping up in the discussions for several of the > >> recent RFCs and I think the time has come to consider moving away > >> from fatal errors. > >> > >> Thoughts? > >> > >> Thanks, > >> Nikita > > > > As a PHP user-space developer I love this idea. However, I share the > > concern of others here that it could result in BC unpleasantness, even > > if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't > > know off hand how various versions of Drupal would handle this. > > > > --Larry Garfield > > How could anything be reliant on the behaviour of a fatal error in any meaningful way ?? > > Cheers > Joe
In plenty of ways: for example currently frameworks can "catch" fatal errors using "register_shutdown_function" and display an error page to the end user (say if there is an attempt to call a method on a null object due to an unanticipated runtime error). Current frameworks might be broken if the way fatal errors work is changed. That would be a BC break. See e.g. http://stackoverflow.com/questions/16284235/zend-framework-error-page-for-php-fatal-errors/16284260#16284260 (This is not a vote for or against this proposal; I'm just answering the immediate parent here.) Best, Rich Richard Bradley Tel : 020 7485 7500 ext 3230 | Fax : 020 7485 7575 softwire Sunday Times Best Small Companies - UK top 20 three years running Web : www.softwire.com | Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

Jordi Boggiano

12 years ago
On Fri, Oct 25, 2013 at 3:55 PM, Richard Bradley <Richard.Bradley@softwire.com> wrote:
>> How could anything be reliant on the behaviour of a fatal error in any meaningful way ?? >> >> Cheers >> Joe > > In plenty of ways: for example currently frameworks can "catch" fatal errors using "register_shutdown_function" and display an error page to the end user (say if there is an attempt to call a method on a null object due to an unanticipated runtime error). > > Current frameworks might be broken if the way fatal errors work is changed. That would be a BC break. > > See e.g. http://stackoverflow.com/questions/16284235/zend-framework-error-page-for-php-fatal-errors/16284260#16284260 > > (This is not a vote for or against this proposal; I'm just answering the immediate parent here.)
Wouldn't this sort of use case be covered by the fact that an uncaught exception would still result in a fatal error? The only case it'd "break" is if you have a try/catch around your entire application, before you had to listen to have a shutdown handler but now your catch would catch the fatal exceptions before they bring everything down. I'd imagine that this RFC would not affect most sane cases of shutdown handlers and related "show a nice error page to users when all hell breaks loose" tricks. Cheers
-- Jordi Boggiano @seldaek - http://nelm.io/jordi

Richard Bradley

12 years ago
> -----Original Message----- > From: Jordi Boggiano [mailto:j.boggiano@seld.be] > Sent: 25 October 2013 15:03 > To: Richard Bradley > Cc: Joe Watkins; internals@lists.php.net; Larry Garfield > Subject: Re: [PHP-DEV] [RFC] Exceptions in the engine > > On Fri, Oct 25, 2013 at 3:55 PM, Richard Bradley <Richard.Bradley@softwire.com> wrote: > >> How could anything be reliant on the behaviour of a fatal error in any meaningful way ?? > >> > >> Cheers > >> Joe > > > > In plenty of ways: for example currently frameworks can "catch" fatal errors using "register_shutdown_function" and display an error page to the end user (say if there is an attempt to call a method on a null object due to an unanticipated runtime error). > > > > Current frameworks might be broken if the way fatal errors work is changed. That would be a BC break. > > > > See e.g. > > http://stackoverflow.com/questions/16284235/zend-framework-error-page- > > for-php-fatal-errors/16284260#16284260 > > > > (This is not a vote for or against this proposal; I'm just answering > > the immediate parent here.) > > Wouldn't this sort of use case be covered by the fact that an uncaught exception would still result in a fatal error? The only case it'd "break" is if you have a try/catch around your entire application, before you had to listen to have a shutdown handler but now your catch would catch the fatal exceptions before they bring everything down.
You might still end up in the register_shutdown_function yes, but the error code would have changed (from error_get_last()) i.e. people may well be relying on the exact behaviour of fatal errors. It would be great to fix the somewhat messy state of exceptions & errors in PHP, but we shouldn't pretend that we can do so without BC breaks. Richard Bradley Tel : 020 7485 7500 ext 3230 | Fax : 020 7485 7575 softwire Sunday Times Best Small Companies - UK top 20 three years running Web : www.softwire.com | Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

George Bond

12 years ago
On 25 October 2013 15:09, Richard Bradley <Richard.Bradley@softwire.com>wrote:
> > -----Original Message----- > > From: Jordi Boggiano [mailto:j.boggiano@seld.be] > > Sent: 25 October 2013 15:03 > > To: Richard Bradley > > Cc: Joe Watkins; internals@lists.php.net; Larry Garfield > > Subject: Re: [PHP-DEV] [RFC] Exceptions in the engine > > > > On Fri, Oct 25, 2013 at 3:55 PM, Richard Bradley < > Richard.Bradley@softwire.com> wrote: > > >> How could anything be reliant on the behaviour of a fatal error in > any meaningful way ?? > > >> > > >> Cheers > > >> Joe > > > > > > In plenty of ways: for example currently frameworks can "catch" fatal > errors using "register_shutdown_function" and display an error page to the > end user (say if there is an attempt to call a method on a null object due > to an unanticipated runtime error). > > > > > > Current frameworks might be broken if the way fatal errors work is > changed. That would be a BC break. > > > > > > See e.g. > > > http://stackoverflow.com/questions/16284235/zend-framework-error-page- > > > for-php-fatal-errors/16284260#16284260 > > > > > > (This is not a vote for or against this proposal; I'm just answering > > > the immediate parent here.) > > > > Wouldn't this sort of use case be covered by the fact that an uncaught > exception would still result in a fatal error? The only case it'd "break" > is if you have a try/catch around your entire application, before you had > to listen to have a shutdown handler but now your catch would catch the > fatal exceptions before they bring everything down. > > You might still end up in the register_shutdown_function yes, but the > error code would have changed (from error_get_last()) > i.e. people may well be relying on the exact behaviour of fatal errors. > > It would be great to fix the somewhat messy state of exceptions & errors > in PHP, but we shouldn't pretend that we can do so without BC breaks. > >
I think as far as BC breaks go, "in the event that my application has already become unusable to the end-user, now only the sensibly-structured catch-all codepath that we had to implement anyway is followed rather than that other much-nastier-to-work-with codepath" is pretty uncontroversial... --G

Stas Malyshev

12 years ago
Hi!
> How could anything be reliant on the behaviour of a fatal error in any > meaningful way ??
If condition X did not occur, fatal error would happen, so in the following code I can safely assume condition X is true without checking it. That logic of course would completely break with non-fatal fatal errors, both in C and in PHP. Oh yes, and people do try {...} catch(Exception e) { /* ignore exceptions */} all the time (without, of course, counting fatal errors as being ignored).
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Joe Watkins

12 years ago
On 10/25/2013 08:20 PM, Stas Malyshev wrote:
> Hi! > >> How could anything be reliant on the behaviour of a fatal error in any >> meaningful way ?? > > If condition X did not occur, fatal error would happen, so in the > following code I can safely assume condition X is true without checking it. > > That logic of course would completely break with non-fatal fatal errors, > both in C and in PHP. > > Oh yes, and people do try {...} catch(Exception e) { /* ignore > exceptions */} all the time (without, of course, counting fatal errors > as being ignored). >
Catch all and error handling hacks to ignore fatals are covered in the RFC, I think satisfactorily, mostly ... I haven't really thought about it too much, it just seemed a bit silly to rely on what is essentially shutdown ... I'm liking the idea of BaseException, for this, and in general, would allow us to avoid the problem of catch all blocks, or at least the ones that are in existence now ... If we really wanted to, we could fix all the code that throws the base Exception, making them throw specialized types, as they should, and include a compiler check that finds catch(Exception) blocks and complains, it shouldn't really be valid, we could encourage people to do things the right way in the hope that someday we won't have to worry about catch all blocks when looking to make improvements ... Cheers Joe

Rowan Collins

12 years ago
On 25/10/2013 20:41, Joe Watkins wrote:
> If we really wanted to, we could fix all the code that throws the base > Exception, making them throw specialized types, as they should
This seems a little contradictory when you're proposing an undifferentiated EngineException, where individual errors would need to be distinguished based on the message string. That's pretty much what throw Exception('Some message'); gives in userland. Besides which...
> and include a compiler check that finds catch(Exception) blocks and > complains, it shouldn't really be valid
I don't think "catch(Exception)" blocks exist as a partner to "throw Exception;" they exist to mark a boundary in code that you don't want any exceptions to cross, or where you want to log all exceptions in some bespoke way. They might be the last in a long string of catch() blocks attached to one try, like the default: label in a switch statement. They might also, as discussed wrt assertions/expectations, be in a unit testing framework.
-- Rowan Collins [IMSoP]

Rowan Collins

12 years ago
On 26/10/2013 13:18, Rowan Collins wrote:
> On 25/10/2013 20:41, Joe Watkins wrote: >> If we really wanted to, we could fix all the code that throws the >> base Exception, making them throw specialized types, as they should > > This seems a little contradictory when you're proposing an > undifferentiated EngineException
Apologies, I'd lost track of the thread a bit - it's not you that's proposing that, so this paragraph is rather mis-targeted.
-- Rowan Collins [IMSoP]

Joe Watkins

12 years ago
On 10/26/2013 01:18 PM, Rowan Collins wrote:
> On 25/10/2013 20:41, Joe Watkins wrote: >> If we really wanted to, we could fix all the code that throws the base >> Exception, making them throw specialized types, as they should > > This seems a little contradictory when you're proposing an > undifferentiated EngineException, where individual errors would need to > be distinguished based on the message string. That's pretty much what > throw Exception('Some message'); gives in userland. > > Besides which... > >> and include a compiler check that finds catch(Exception) blocks and >> complains, it shouldn't really be valid > > I don't think "catch(Exception)" blocks exist as a partner to "throw > Exception;" they exist to mark a boundary in code that you don't want > any exceptions to cross, or where you want to log all exceptions in some > bespoke way. They might be the last in a long string of catch() blocks > attached to one try, like the default: label in a switch statement. They > might also, as discussed wrt assertions/expectations, be in a unit > testing framework. >
They _should_ exist as a boundary, a last resort, if at all, but when they do exist they are no such boundary or last resort, they are normal catch blocks because the core throws the base Exception ... I'm just making the observation that it's not a very good idea to do that, doesn't take a lot to fix, has no bc issues and sets the right kind of standard. An EngineException is just that, an Exception from the Engine, that makes sense, an Exception coming from Date, doesn't make sense, that should be a DateException, it's not dependant on or descended from EngineException at all, it would just be better form if exceptions thrown from the core meant something so that catch all exception blocks when they are used are just as we all know they should be - a last resort, if present at all. Maybe emitting a warning is a bit pedantic ... Anyway, carry on with the discussion at hand, which is not about any of this at all, I was just saying it might be nice if we are to start using exceptions from core _as a policy_ to make good, as good as possible, our use of exceptions so far. Cheers Joe

Rowan Collins

12 years ago
On 26/10/2013 15:26, Joe Watkins wrote:
> They _should_ exist as a boundary, a last resort, if at all, but when > they do exist they are no such boundary or last resort, they are > normal catch blocks because the core throws the base Exception ... I'm > just making the observation that it's not a very good idea to do that, > doesn't take a lot to fix, has no bc issues and sets the right kind of > standard.
Right, I'm agreed that throw statements should be as specific as possible, both in core/extensions and in userland. But you seemed to link that somehow to catch(Exception) blocks, which are an entirely different topic, and have valid use cases, since they mean "catch everything descended from this class" not "catch things with this exact class". Regards the engine throwing exceptions, it's the catch side of things which is most relevant.
-- Rowan Collins [IMSoP]

Rowan Collins

12 years ago
On 25/10/2013 14:02, Joe Watkins wrote:
> On 10/24/2013 11:31 PM, Larry Garfield wrote: >> As a PHP user-space developer I love this idea. However, I share the >> concern of others here that it could result in BC unpleasantness, even >> if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't >> know off hand how various versions of Drupal would handle this. >> >> --Larry Garfield > > How could anything be reliant on the behaviour of a fatal error in any > meaningful way ??
I think there's an important distinction between "not breaking any backwards compatibility" and "breaking backwards compatibility in an acknowledged way having weighed the impact". A change is only 100% backwards compatible if an existing valid script would behave identically on the old and new versions, with the change only being visible if the programmer explicitly takes advantage of it. The short-hand array syntax fulfilled this requirement, to the best of my knowledge; the introduction of Traits didn't quite, because it reserved a few keywords, but that was its only impact. Throwing exceptions for things which were previously fatal errors will change the behaviour of existing scripts in several ways, some of which are the stated aims of the RFC: 1. Messages previously issuing E_RECOVERABLE_ERROR will no longer trigger handlers registered with set_error_handler() 2. It will no longer be possible to catch an E_RECOVERABLE_ERROR and continue in the same context 3. If all uses of E_RECOVERABLE_ERROR are converted to exceptions, that constant will become redundant, and all uses of it, e.g. in error_reporting() bitmasks, will become meaningless. 4. catch(Exception) blocks will pick up the errors, unless a BaseException is introduced 5. The handler registered with set_exception_handler() will (presumably) be called for such errors 6. If a BaseException *is* introduced, typehints of class Exception will fail for some exception objects (I spotted this noting that the documentation for set_exception_handler implies a callback with such a typehint) 7. Finally blocks and destructors will be called when an error occurs 8. As a consequence of the above, previously impossible codepaths and program states will become possible 9. It will become possible for multiple "fatal" errors to occur in a single script execution, since code will continue executing after the first is thrown as an exception I don't think there can be any doubt that this change would break *some* backwards compatibility, even if a BaseException is introduced (which seems sensible) and E_RECOVERABLE_ERRORs are left untouched (which seems unfortunate). The question then becomes if it is an *acceptable* break, due to the behaviours affected being considered marginal enough to ignore - and also whether the value of having this in 5.x outweighs the cost. Don't get me wrong, I would love to see error handling in PHP cleaned up, but I'm not convinced that doing it piecemeal in non-breaking steps is either possible or desirable. I'd like to see this expanded into a fully considered mechanism which would be a fitting backbone for a major release.
-- Rowan Collins [IMSoP]

Julien Pauli

12 years ago
On Sat, Oct 26, 2013 at 3:14 PM, Rowan Collins <rowan.collins@gmail.com>wrote:
> On 25/10/2013 14:02, Joe Watkins wrote: > >> On 10/24/2013 11:31 PM, Larry Garfield wrote: >> >>> As a PHP user-space developer I love this idea. However, I share the >>> concern of others here that it could result in BC unpleasantness, even >>> if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't >>> know off hand how various versions of Drupal would handle this. >>> >>> --Larry Garfield >>> >> >> How could anything be reliant on the behaviour of a fatal error in any >> meaningful way ?? >> > > I think there's an important distinction between "not breaking any > backwards compatibility" and "breaking backwards compatibility in an > acknowledged way having weighed the impact". > > A change is only 100% backwards compatible if an existing valid script > would behave identically on the old and new versions, with the change only > being visible if the programmer explicitly takes advantage of it. The > short-hand array syntax fulfilled this requirement, to the best of my > knowledge; the introduction of Traits didn't quite, because it reserved a > few keywords, but that was its only impact. > > Throwing exceptions for things which were previously fatal errors will > change the behaviour of existing scripts in several ways, some of which are > the stated aims of the RFC: > > 1. Messages previously issuing E_RECOVERABLE_ERROR will no longer > trigger handlers registered with set_error_handler() > 2. It will no longer be possible to catch an E_RECOVERABLE_ERROR and > continue in the same context > 3. If all uses of E_RECOVERABLE_ERROR are converted to exceptions, that > constant will become redundant, and all uses of it, e.g. in > error_reporting() bitmasks, will become meaningless. > 4. catch(Exception) blocks will pick up the errors, unless a > BaseException is introduced > 5. The handler registered with set_exception_handler() will > (presumably) be called for such errors > 6. If a BaseException *is* introduced, typehints of class Exception > will fail for some exception objects (I spotted this noting that the > documentation for set_exception_handler implies a callback with such > a typehint) > 7. Finally blocks and destructors will be called when an error occurs > 8. As a consequence of the above, previously impossible codepaths and > program states will become possible > 9. It will become possible for multiple "fatal" errors to occur in a > single script execution, since code will continue executing after > the first is thrown as an exception > > I don't think there can be any doubt that this change would break *some* > backwards compatibility, even if a BaseException is introduced (which seems > sensible) and E_RECOVERABLE_ERRORs are left untouched (which seems > unfortunate). > > The question then becomes if it is an *acceptable* break, due to the > behaviours affected being considered marginal enough to ignore - and also > whether the value of having this in 5.x outweighs the cost. > > Don't get me wrong, I would love to see error handling in PHP cleaned up, > but I'm not convinced that doing it piecemeal in non-breaking steps is > either possible or desirable. I'd like to see this expanded into a fully > considered mechanism which would be a fitting backbone for a major release.
+1 for the last ideas. I'm not +1 for having such a change in the 5.x branch. However, I'm full +1 to have this change + others (Warnings, Notices, etc... to exceptions), having refactored all the code ; for a 6.x branch or whatever major number it'll be. Starting trying to keep some BC, but not all, to make people half happy, but not too much nor less , is just a mistake, IMO. it will add confusion and mess in PHP, and we don't really need that :-p Your ideas are great, the patch is at an advanced stage , but such ideas and changes should definetly not go for 5.x branch. About next major, we have not decided yet which next version PHP will be. We all talked about a possible 5.6 , but if we could have a massive contribution wave, with great ideas like this one , then we could break BC, and make PHP-next a major release. Julien.Pauli

Larry Garfield

12 years ago
On 10/26/2013 11:26 AM, Julien Pauli wrote:
> On Sat, Oct 26, 2013 at 3:14 PM, Rowan Collins <rowan.collins@gmail.com>wrote: > >> On 25/10/2013 14:02, Joe Watkins wrote: >> >>> On 10/24/2013 11:31 PM, Larry Garfield wrote: >>> >>>> As a PHP user-space developer I love this idea. However, I share the >>>> concern of others here that it could result in BC unpleasantness, even >>>> if limited to the E_FATAL and E_RECOVERABLE_FATAL use cases. I don't >>>> know off hand how various versions of Drupal would handle this. >>>> >>>> --Larry Garfield >>>> >>> How could anything be reliant on the behaviour of a fatal error in any >>> meaningful way ?? >>> >> I think there's an important distinction between "not breaking any >> backwards compatibility" and "breaking backwards compatibility in an >> acknowledged way having weighed the impact". >> >> A change is only 100% backwards compatible if an existing valid script >> would behave identically on the old and new versions, with the change only >> being visible if the programmer explicitly takes advantage of it. The >> short-hand array syntax fulfilled this requirement, to the best of my >> knowledge; the introduction of Traits didn't quite, because it reserved a >> few keywords, but that was its only impact. >> >> Throwing exceptions for things which were previously fatal errors will >> change the behaviour of existing scripts in several ways, some of which are >> the stated aims of the RFC: >> >> 1. Messages previously issuing E_RECOVERABLE_ERROR will no longer >> trigger handlers registered with set_error_handler() >> 2. It will no longer be possible to catch an E_RECOVERABLE_ERROR and >> continue in the same context >> 3. If all uses of E_RECOVERABLE_ERROR are converted to exceptions, that >> constant will become redundant, and all uses of it, e.g. in >> error_reporting() bitmasks, will become meaningless. >> 4. catch(Exception) blocks will pick up the errors, unless a >> BaseException is introduced >> 5. The handler registered with set_exception_handler() will >> (presumably) be called for such errors >> 6. If a BaseException *is* introduced, typehints of class Exception >> will fail for some exception objects (I spotted this noting that the >> documentation for set_exception_handler implies a callback with such >> a typehint) >> 7. Finally blocks and destructors will be called when an error occurs >> 8. As a consequence of the above, previously impossible codepaths and >> program states will become possible >> 9. It will become possible for multiple "fatal" errors to occur in a >> single script execution, since code will continue executing after >> the first is thrown as an exception >> >> I don't think there can be any doubt that this change would break *some* >> backwards compatibility, even if a BaseException is introduced (which seems >> sensible) and E_RECOVERABLE_ERRORs are left untouched (which seems >> unfortunate). >> >> The question then becomes if it is an *acceptable* break, due to the >> behaviours affected being considered marginal enough to ignore - and also >> whether the value of having this in 5.x outweighs the cost. >> >> Don't get me wrong, I would love to see error handling in PHP cleaned up, >> but I'm not convinced that doing it piecemeal in non-breaking steps is >> either possible or desirable. I'd like to see this expanded into a fully >> considered mechanism which would be a fitting backbone for a major release. > > +1 for the last ideas. > > I'm not +1 for having such a change in the 5.x branch. > However, I'm full +1 to have this change + others (Warnings, Notices, > etc... to exceptions), having refactored all the code ; for a 6.x branch or > whatever major number it'll be. > > Starting trying to keep some BC, but not all, to make people half happy, > but not too much nor less , is just a mistake, IMO. it will add confusion > and mess in PHP, and we don't really need that :-p > Your ideas are great, the patch is at an advanced stage , but such ideas > and changes should definetly not go for 5.x branch. > > About next major, we have not decided yet which next version PHP will be. > We all talked about a possible 5.6 , but if we could have a massive > contribution wave, with great ideas like this one , then we could break BC, > and make PHP-next a major release. > > Julien.Pauli
I have to agree with both of these. "It's a BC break but we've weighed it and decided it's OK" may sound good, but it's one of the key reasons that this is still the case: http://w3techs.com/technologies/details/pl-php/5/all There are more users of PHP 5.1 than there are of 5.5, and 5.4 is still less than 10% of the market. 5.3, already EOLed, only just recently surpassed 5.2 this year. This is why we (user-space developers) can't have nice things. :-) New versions of PHP have very nice things, but mass-market hosts, sysadmins, and anyone else with legacy code is extremel squeamish about upgrading to new PHP versions for fear of breaking things. That holds back the whole industry. I'd love to switch to exceptions properly in PHP, but I think it's better done as part of a for-reals switch to PHP 6, where some BC-breaking changes are allowed but cross-version compatibility is still possible. (As was the case with PHP 4->PHP5. "Well behaved" code from PHP 4.4 can still run today on 5.5, but the definition of "well behaved" wasn't necessarily known at the time of 4.2. It needs to be possible to write code that runs properly in both 5.late and 6.x, or no one will switch to 6.x) Back on topic then... +1 to engine level exceptions... in PHP 6. Which should happen sooner rather than later. --Larry Garfield

Alexey Zakhlestin

12 years ago
On 24 окт. 2013 г., at 21:41, Nikita Popov <nikita.ppv@gmail.com> wrote:
> I'd like to propose an RFC, which allows the use of exceptions within the > engine and also allows changing existing fatal errors to exceptions: > > https://wiki.php.net/rfc/engine_exceptions > > This topic has been cropping up in the discussions for several of the > recent RFCs and I think the time has come to consider moving away from > fatal errors. > > Thoughts?
Thank you, Nikita! That’s something which definitely needs to be done. Catching parse-errors from includes, bad function/method calls, etc. will let us make complex code-bases more robust and predictable. I think introduction of BaseException is a necessity. This way code will stay compatible and new exceptions will just end their life somewhere in shutdown-handler, just as fatal errors do now. Rowan proposed to use subclasses for different exception types — I believe it can wait a bit. There is no need to overcomplicate this. New classes would be added eventually, but as they will be extending EngineException forward-compatibility is preserved. converting fatal-errors is a safe-enough change to be done in 5.NEXT. converting some of the warnings is a good topic for starting 6.x
-- Alexey Zakhlestin CTO at Grids.by/you https://github.com/indeyets PGP key: http://indeyets.ru/alexey.zakhlestin.pgp.asc

Clint Priest

12 years ago
On 10/24/2013 12:41 PM, Nikita Popov wrote:
> https://wiki.php.net/rfc/engine_exceptions
Very nice Nikita... I like that this patch would provide for very little BC breakage. Given Rowan's list, there would be some changes in behavior but I think that the behavior would be desirable for those that have written their code in this manner (that finally's and destructors will be called, etc). It might even be likely that those who have written code in this manner are not aware that their code isn't being unwound properly, I've run across situations like this before and am always a little leery of writing code that relies on destructors being called since it is not perfectly reliable. On the potential issues: +1 for BaseException -1 for E_RECOVERABLE becoming exceptions because of the BC breakage (execution flow should continue on the next line) +1 for the final error message being reduced to Uncaught EngineException... -1 for not all errors converted, if it's an error that occurs after code execution has begun then they should all be converted for consistency. On other ideas presented as comments: -1 for changing any current errors that let code execution continue (E_WARNING, E_NOTICE, etc) into exceptions. In the end, I think that the current RFC takes it to where it really needs to be: proper unwinding of finally/destructors, better uncaught fatal error information (stack traces). Some other languages go way too far with exceptions and make writing anything in them consist of 30% of the code being try/catch blocks rather than real code. The only thing I would suggest is that it not being a single EngineException, but a few well thought out sub-classes of EngineException. -Clint

Joe Watkins

12 years ago
On 10/26/2013 08:23 PM, Clint Priest wrote:
> On 10/24/2013 12:41 PM, Nikita Popov wrote: >> https://wiki.php.net/rfc/engine_exceptions > The only thing I would suggest is that it not being a single > EngineException, but a few well thought out sub-classes of EngineException. > > -Clint
Actually this does make sense when you think about it ... So +1 to that ... I've still not really managed to organize all my thoughts into a coherent opinion on the things brought up, I'm not sure I see the major BC issues that other people do. Like Clint has mentioned this is as far as it needs to go now, I think that's probably where I'm at ... Cheers