Re: [PHP-DEV] exit() via exception

This is only part of a thread. view whole thread
October 11, 2019 18:49 (Stanislav Malyshev)

> For me, one of the most annoying things about this is that we can't perform > proper leak checks on code using PhpUnit, because it will always exit() at > the end, which will result in "expected" memory leaks.
Is that something that might be fixed in phpunit? I am not familiar with this specific issue but I'm not sure why unit test code can't use some other way to end whatever it's doing than exit() if that's the issue. Is it about the exit codes? If so, this probably can be fixed by other means?
> I think it would be good to switch exit() to work by throwing a magic > exception, similar to what Python does. This would allow us to properly > unwind the stack, executing finally blocks (which are currently skipped) > and perform a clean engine shutdown.
True, but that means exit() would become a) significantly slower b) may change semantics, which may or may not be a good thing. Also there's a possibility of exit() failing then which is not something we've had before.
> Depending on the implementation, we could also allow code to actually catch > this exception, which may be useful for testing scenarios, as well as > long-running daemons.
I don't think this is a particularly good idea - first of all, using exception for flow control is wrong. Second of all, if you _want_ to use exceptions for flow control, you already can. If the code uses exit(), it usually means exit, as in drop everything and get the heck out. It may not expect that lots of code will run after that (yes, I know, shutdown handlers, but they have to be clearly installed as such) that may still do a lot of stuff - while the state of the app is potentially broken. If we make exit catchable, then the next request would be to implement real, un-catchable, exit that actually implements the old semantics. Sometimes people don't care about memory leaks checking but want to just abandon the boat and let the memory manager to clean up the mess (or even not that, just kill the process and be done).
> I'm mainly wondering how exactly we'd go about integrating this in the > existing exception hierarchy. Assuming that it is desirable to allow people > to actually catch this exception, my first thought would be along these > lines:
I don't think it should be Throwable, since you a) can't and shouldn't actually throw it and b) code that catches Throwable does not expect to catch exits, so it would break its semantics. Granted, there's almost never is the reason to catch Throwable, but if you already do, you'd be in for a nasty surprise.
> Throwable (convert to abstract class) > \-> Exception > \-> Error > \-> ExitThrowable > > This does mean though that existing code using catch(Throwable) is going to > catch exit()s as well. This can be avoided by introducing *yet another* > super-class/interface above Throwable, which is something I'd rather avoid.
If you want to do weird things - like have exception that it's really not an exception - you'd have weird hierarchy. Either that, or you make existing hierarchy weird, which existing code (and virtually everybody writing new code) does not expect. I think theoretical weirdness is better than nasty surprise for the practical users - which would either have to insert instanceof checks into their catches, or deal with exit() behaving wrongly. -- Stas Malyshev