Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126552 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id E51FF1A00BC for ; Mon, 3 Mar 2025 15:09:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741014436; bh=8yJAchUz99x3wAwYqfhfTHZjLtaYKXQ8ZOGD7ZC0raQ=; h=From:To:Subject:Date:In-Reply-To:References:List-Id:List-Post: From; b=GpbBI4XXJLn89BqgrSe5flnbahwT6LrPrrc4jkuI+/vz5yX3My6oZYzKYdQtxSslk ziukIO8AxeYTHtWAdgXCTVPjCTJJ9IM10uGYb12Ic9oVTpapzuDVVu5BtbEx5nbfcz oD6h7Q6QsEligT0EZN0OtTXB8UPaRb0ew9oIZI6tPCU8OKmbo65H46R6CZTrIYguhA SJ4+IUJtrxlslhhHjWFXbq31aIL9D2DGHvc73DwJfGHcpGwbLEuEWZBn5fs2+MP1NG nl8TUsg2KmgjR/NwPWK2kyZhKNQ9RmIWDoD48Tp9WjxggtxdxviM2yU6qxQ5PfGtYz rw1qj/eWi+JlQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id EF11B1801D8 for ; Mon, 3 Mar 2025 15:07:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_FONT_LOW_CONTRAST,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,T_KAM_HTML_FONT_INVALID autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 3 Mar 2025 15:07:14 +0000 (UTC) Received: by mail-ed1-f49.google.com with SMTP id 4fb4d7f45d1cf-5dca468c5e4so8066860a12.1 for ; Mon, 03 Mar 2025 07:09:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741014590; x=1741619390; darn=lists.php.net; h=mime-version:user-agent:list-post:list-id:references:in-reply-to :date:subject:to:from:message-id:from:to:cc:subject:date:message-id :reply-to; bh=3I0hrzB3YsaYyNvt7wa+W92TGObKwF5nO8FhGMlZbgw=; b=AvDVdNKKC07NI3UFBPcE0YK1HgctX24+tnzmQYUI/ug4j3g5ATeVCDGNmxadeZW5Lz A0PWTU8SjUUCABJfqgE6PIZY4olEFCf6P6dTB4xz0shBi2iEEpJwr67QsBJgAZoJ6yu/ vamOBBP6xig0BOye9/jcS4oEsBAt9AwzFRQSpXl2HqEiptFX1QcW4uRd5bbjnkksYg8z 6Wl8TEwSQIiCjNr9ErOpI1Q2ggOsp2eYy0Pfk+UbKWlbYjEi2HUUd3+ZTi1blkT2dG7m TEKOvOGwhB0m1qrPWwMspCZNVLc7HLGUbEuN+0nw9xzugSF0sUmMfZ8T0MQ4uBVn8T4M OGFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741014590; x=1741619390; h=mime-version:user-agent:list-post:list-id:references:in-reply-to :date:subject:to:from:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3I0hrzB3YsaYyNvt7wa+W92TGObKwF5nO8FhGMlZbgw=; b=cNtt3oRWvBz8nbaJ32AmkwwQtbtvCQAftU2SvLUyu5ylMjI5wH8A6h7R1pYPQ98FsQ 7BbSCn9ScVdRs89MKnGW83PAl/FVrIqkz00WtpGtCM1MEPrtWT4Mh7AuR0U6zAL7zsYp 6+zsrAiopy87MWdWabnrosMkth2DTyBOr3oSmgNIJksYYSFFmwgF2Onddq8Jcv1i59Ic ofHgBTVr1PsB0AqVwZx8nAcvs5J0cap9q+/xV8cWA6AY4D2qOV5LARU8O53dB9rw5Yl2 qdOCYZ5yg5p4cTKEfPKqcJDOCPESG6R5LS4f1TE199FAmiU9lIWHv/M2u5Ne4+BEiFwC iJzQ== X-Forwarded-Encrypted: i=1; AJvYcCVn+tIvvc9AdLRGEZjkLWxZdwUBAMZe6SeFTnfrBINaUjAsrEc/TvBYUltTXrxbb914MmSzCLhl6BA=@lists.php.net X-Gm-Message-State: AOJu0YwuXJkZoE/YTIQLmPZPtG/cX1LW3eaCw9rJxrG2R8oOF0yYtxdV 6pvXIHSwoS3rjXllj915yNxWAupvZjyfpxQV0A9WU0ULJuWGuuz1dFHAJArG X-Gm-Gg: ASbGncugB4ndQvKGEOx4l9v12tuI1PFgHUARQzuFJe5wBiGZzPI6mvB4VeKgGh2nTfR GfnLqllwqeCCpWNKkGApPOGtQTxi5rjsDlIQ8Tuak2SfnKL+3FEdMxECoxoTEjTtRmynnkSU2xp BfjXvTd0tTiNsHD1FVS7LNZf56at30F7Q3zlqK8g4B/s5PO1VAhlnxYjIpsV1ntS3bQfsFtKtmk ur1oohpKIHMME2iFTzNmMXgIoYgaiiZDXI5h7M4V8C+FMd9bBx2xBsgojmreycEnKyH55lAXsSn lQsu3D7J70IDGRj4WZNboxZJSkcZcjGrQka4GThgaOMIezUER0/Ivm4n3HXiinty X-Google-Smtp-Source: AGHT+IGK9Hor1UZ4nm7RiOQSrEdS9BSDjoOWVSVHtf4Vv1e5nZgaOQ4rrpu6xO1TxwxsJYxrmtffYw== X-Received: by 2002:a05:6402:4307:b0:5de:3c29:e834 with SMTP id 4fb4d7f45d1cf-5e4d6b85f68mr15281541a12.27.1741014589450; Mon, 03 Mar 2025 07:09:49 -0800 (PST) Received: from noip.localdomain ([77.239.166.57]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5e4c3b4aa3bsm6924938a12.16.2025.03.03.07.09.48 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 03 Mar 2025 07:09:48 -0800 (PST) Content-Type: multipart/alternative; boundary="----sinikael-?=_1-17410145883220.45410162249824015" Message-ID: <1741011949553.2796973485.548949007@gmail.com> To: Daniil Gentili , internals@lists.php.net Subject: Re: [PHP-DEV] PHP True Async RFC Date: Mon, 03 Mar 2025 15:09:48 +0000 In-Reply-To: References: List-Id: internals.lists.php.net List-Post: X-Mailer: Vivaldi Mail User-Agent: Vivaldi Mail/7.1.3570.50 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 From: edmond.ht@gmail.com (Edmond Dantes) ------sinikael-?=_1-17410145883220.45410162249824015 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable I like context.WithCancel from Go, but it can essentially be implemented = directly in PHP land since all the necessary tools are available. Note, this is precisely the problem, implement cancellation propagation to = child fibers in userland PHP requires writing a bunch of boilerplate = try-catch blocks to propagate CancellationExceptions to child = FutureHandle::cancel()s (spawning multiple fibers to execute subtasks = concurrently during an async method call is pretty common, and the current = implicit cancellation mode requires writing a bunch of try-catch blocks to = propagate cancellation, instead of just passing a cancellation object, or a= flag to inherit the cancellation of the current fiber when spawning a new = one). Catching CancellationException is only necessary if there is some defer = code. If there isn't, then there's no need to catch it. Try-catch blocks are not = mandatory. We can create a Cancellation object, pass it via use or as a parameter to = all child fibers, and check it in await(). This is the most explicit = approach. In this case, try-catch would only be needed if we want to clean = up some resources. Otherwise, we can omit it. According to the RFC, if a fiber does not catch CancellationException, it = will be handled by the Scheduler. Therefore, catching this exception is not= strictly necessary. If this solution also seems too verbose, there is another one that can be = implemented without modifying this RFC. For example, implementing a = cancellation operation for a Context. All coroutines associated with this = context would be canceled. From an implementation perspective, this is = essentially iterating over all coroutines and checking which context they = belong to.=20 Note the explicit use case I listed is that of an unlock() in a finally = block that *requires spawning a new fiber* in order to execute the actual = unlock() RPC call: this is explicitly in contrast with the RFC, which = specifies that=20 So, if I understand correctly, the code in question looks like this: try { lock(); ... } finally { unlock(); } function unlock() { async\run(); } If I got it right, then the following happens: The code inside try {} allocates resources. The code inside finally {} also allocates resources. So, what do we get? We're trying to terminate the execution of a fiber, and= instead, it creates a new one. It seems like there's a logical error here.= Instead of creating a new fiber, it would be better to use microtasks. I would really prefer it to be always enabled, no fallback at all, because = as I said, it will make absolutely no difference to legacy, non-async = projects that do not use fibers, but it will avoid a split ecosystem = scenario. I'm not arguing at all that avoiding the call to this function is a good = solution. I=E2=80=99m on your side. The only question is how to achieve = this technically. Could you describe an example of "ecosystem split" in the context of this = function? What exactly is the danger? I see no reason why it should break the contract, if implemented by = isolating the global state of each fiber, it can be treated as a mere = implementation detail of the (eventually new) SAPI. So, I can take NGINX and FCGI, and without changing the FCGI interface = itself, but modifying its internal implementation, get a working = application. Yes, but... that means all global variables, including static = ones, need to be tied to the context. It's not that it can't be done, but = what about memory consumption. I'm afraid that if the code wasn't designed for a LongRunning APP, it's = unlikely to handle this task correctly. --=20 Ed. ------sinikael-?=_1-17410145883220.45410162249824015 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


I like = context.= WithCancel from Go, = but it can essentially be implemented directly in PHP land since all the = necessary tools are available.


Not= e, this is precisely the problem, implement cancellation propagation to = child fibers in userland PHP requires writing a bunch of boilerplate = try-catch blocks to propagate CancellationExceptions to child = FutureHandle::cancel()s (spawning multiple fibers to execute subtasks = concurrently during an async method call is pretty common, and the current = implicit cancellation mode requires writing a bunch of try-catch blocks to = propagate cancellation, instead of just passing a cancellation object, or a= flag to inherit the cancellation of the current fiber when spawning a new = one).

Catching Cancellat= ionException is only necessary if there is some defer code.
If there isn't, then there's no need to= catch it. Try-catch blocks are not mandatory.

We can create a Cancellation object, pass it via use or as a parameter to all = child fibers, and check it in await(). This is the most explicit approach. In = this case, try-catch would only be needed if we want to clean up some = resources. Otherwise, we can omit it.

According to the= RFC, if a fiber does not catch CancellationException, it will be handled by the = Scheduler. Therefore, = catching this exception is not strictly necessary.

If this = solution also seems too verbose, there is another one that can be = implemented without modifying this RFC. For = example, implementing a cancellation operation for a Context. All coroutines associated with this context would= be canceled. From an implementation perspective, this is essentially = iterating over all coroutines and checking which context they belong to.=  


Note the explicit use case I listed is that of an = unlock() in a finally block that *requires spawning a new fiber* in order = to execute the actual unlock() RPC call: this is explicitly in contrast = with the RFC, which specifies that 

<= /blockquote>

So, if I understand correctly, the code in = question looks like this:

try { lock(); ... } finally { unlock(); }

function unlock() {
    = async\run();
}

If I got it right, then the following happens:

  • The code inside try {} allocates resources.
  • The code inside finally {} also allocates resources.

So, what do we get? We're trying to = terminate the = execution of a fiber, and instead, it creates a new one. It seems like there's a= logical error here.=

Instead of creating a new fiber, it would be better to = use microtasks.=



I would = really prefer it to be always enabled, no fallback at all, because as I = said, it will make absolutely no difference to legacy, non-async projects = that do not use fibers, but it will avoid a split ecosystem scenario.=

I'm not arguing at all that avoiding the call to this = function is a good solution. I=E2=80=99m on your side. The only question is= how to achieve this = technically.

Could you describe an example of = "ecosystem split" in = the context of this function? What exactly is the danger?=



I see no reason why it should break the contract, if = implemented by isolating the global state of each fiber, it can be treated = as a mere implementation detail of the (eventually new) SAPI.=
=

So, I can take NGINX and FCGI, and without changing the= FCGI interface itself, but modifying its internal implementation, get a = working application. Yes, but... that means all global variables, including= static ones, need to be tied to the context. It's not that it can't be = done, but what about memory consumption.

I'm = afraid that if the code wasn't designed for a LongRunning APP, it's unlikely to handle this = task correctly.


--&nbs= p;
Ed.
------sinikael-?=_1-17410145883220.45410162249824015--