Re: exit() via exception
| From: | Marcio Almada | 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