Re: exit() via exception

From: Date: Fri, 11 Oct 2019 13:47:03 +0000
Subject: Re: exit() via exception
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-107505@lists.php.net to get a copy of this message
Em sex, 11 de out de 2019 às 08:05, Nikita Popov <nikita.ppv@gmail.com> escreveu: > > Hi, > Hello :) > Currently exit() is implemented using bailout and unclean shutdown, which > means that we're going to perform a longjmp back to the top-level scope and > let the memory manager clean up all the memory it knows about. Anything not > allocated using ZMM is going to leak persistently. > > 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. > > 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. > > 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'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: > > 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. > Since you brought python as inspiration, I believe the hierarchy goes like this on their land: BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- [kitchen sink] Being BaseException the base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes. It 's the equivalent to our Throwable situation. In this context ExitThrowable -> Throwable appears legit. > > Anyone have thoughts on this matter? > Yes. There is an obvious can of worms if I've got this right: exit() and die() would no longer guarantee a program to actually terminate in case catching ExitThrowable is allowed. Python solves this by actually having two patterns: 1. quit(), exit(), sys.exit() are the equivalent to `raise SystemExit`, can be caught / interrupted 2. os._exit(), can't be caught but has a callback mechanism like our register_shutdown_function, see https://docs.python.org/3/library/atexit.html If we bind exit() and die() to a catchable exception how would we still have the scenario 2 available on PHP land without a BCB? :) I have one simple suggestion: Introduce EngineShutdown -> Throwable, bind exit|die to it but disallow catch(\EngineShutdown $e) at compile time. This would allow keeping backwards compatibility to scenario 2 without messing with our current exception hierarchy. > Nikita Thanks, Márcio

« previous php.internals (#107505) next »