Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:107508 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 7345 invoked from network); 11 Oct 2019 16:28:47 -0000 Received: from unknown (HELO php-smtp3.php.net) (208.43.231.12) by pb1.pair.com with SMTP; 11 Oct 2019 16:28:47 -0000 Received: from php-smtp3.php.net (localhost [127.0.0.1]) by php-smtp3.php.net (Postfix) with ESMTP id 5B42B2D200A for ; Fri, 11 Oct 2019 07:11:57 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp3.php.net X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: X-Spam-Virus: No Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp3.php.net (Postfix) with ESMTPS for ; Fri, 11 Oct 2019 07:11:56 -0700 (PDT) Received: by mail-lf1-x129.google.com with SMTP id x80so7172709lff.3 for ; Fri, 11 Oct 2019 07:11:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=BLUxFTNsVAWykP85aeDLOfVlu/I6QIcIvxj4IS5LWn0=; b=X3xAB0s6tn0sdxOXlPKzajxBfzf6cz6CQQ/RkMkco+GiJKnSsT3W5UKgOJIf7QMZ8g 7voK/pjbAFA9DYYQO2Kkt9YXcg+Pu+wP7csyBBYb7lde9FTbIJc0ObwFGwd73vTt4Qab rY+aAwtHXVRTm04usgxS0FrgZV4sQXkO3RCjX4LYKEhJU+lmfKKlljmsWDBqhXtZ+wDT xBKn+XuJ3LZjakVZieumTF65nFRRQvtJBPAFXgOkct+t8yp6zGqjoRKk56xxweL22VaA piy+VoTuaBOA+NBc17zvIGY7En6UfGuaI7g0MDufJDvxNz4kidGA3uxMJ6DBKlcSlviY zrJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=BLUxFTNsVAWykP85aeDLOfVlu/I6QIcIvxj4IS5LWn0=; b=E8SLAhE+visgdwqhCnBqDn2S1zUT+2lpfT24BwtPAAtzHW0g+2LgcEL+BgMhWInWae jLusrRooD6bKOZgwyJDWUHMEl75UsZUMagGHkvKhzdce1zsgO2YKTUMB26d+qG1oWs51 zNga4CyUjrAdhr0HjZA45GH2qV09zGSZIXNRhxgJ0J+1QGWhKDCpjtL3J66bdLsxIcAm 1VBF3PMSDp2m141tMrHTGpzDgTx5S8fzPLmbcVxussq85DTM0OUBsYXGNg8XpIMcj42j oeAg9TPJVzPKybl+Z0YsrgokomG5s9h7bF836PmtjNE1J6k45jvNU9fIpA9/PgtmxAx1 opoQ== X-Gm-Message-State: APjAAAU8QbRFPuDymsxILoOFNusDRKIy/CBr6YJ9JP7MEHe1mHDT87HF dk018M02+m1MYZD0DD0a4qVlGMzjVr7Drj1qo94= X-Google-Smtp-Source: APXvYqzCOq90KYPS/VgfxHCEyzP/zZaTl6G4Kl4oSqbinFJAs5dc7TL2I/ua/aBqD+U6UMY0QqPL5EpKogZNC8f8lvI= X-Received: by 2002:a19:f813:: with SMTP id a19mr9171106lff.154.1570803115370; Fri, 11 Oct 2019 07:11:55 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 11 Oct 2019 16:11:39 +0200 Message-ID: To: Marcio Almada Cc: PHP internals Content-Type: multipart/alternative; boundary="000000000000b42d990594a31909" X-Envelope-From: Subject: Re: [PHP-DEV] exit() via exception From: nikita.ppv@gmail.com (Nikita Popov) --000000000000b42d990594a31909 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Fri, Oct 11, 2019 at 3:47 PM Marcio Almada wrote= : > Em sex, 11 de out de 2019 =C3=A0s 08:05, Nikita Popov > escreveu: > > > > Hi, > > > > Hello :) > > > Currently exit() is implemented using bailout and unclean shutdown, whi= ch > > 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 goin= g > 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 I don't believe atexit applies to os._exit(). In any case, I agree that this is something we're currently missing -- we should probably add a pcntl_exit() for this purpose. It should be noted though that this is really very different from exit(), which is still quite graceful and usable in a webserver context, while a hypothetical pcntl_exit() would bring down the server process. As the Python docs mention, the primary use-case would be exiting from forked processes without going through shutdown, which has also recently come up in https://github.com/php/php-src/pull/4712. > 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. > I think the options are basically: 1. Making EngineShutdown implement Throwable, which would make existing catch(Throwable) catch it -- probably a no-go. 2. Making EngineShutdown not implement Throwable, which means that not all "exceptions" implement the interface, which is rather odd. It still allows explicitly catching the exit. 3. Introducing a function like catch_exit(function() { ... }). This would still allow catching exits (for phpunit + daemon use cases), but the fact that this is actually implemented based on an exception would be hidden and the only way to catch the exit is through this function. 4. Don't allow catching exits at all. In this case the exception is just an implementation detail. Nikita --000000000000b42d990594a31909--