[MacPorts] #38293: php: Enable Thread Safety (was: php54 @5.4.12 Enable Thread Safety)
MacPorts
noreply at macports.org
Mon Apr 22 23:29:31 UTC 2024
#38293: php: Enable Thread Safety
------------------------------+------------------------
Reporter: waltersonntag@… | Owner: ryandesign
Type: enhancement | Status: new
Priority: Normal | Milestone:
Component: ports | Version: 2.1.3
Resolution: | Keywords:
Port: php |
------------------------------+------------------------
Changes (by ryandesign):
* cc: jonaskohl (added)
* port: php54 => php
Comment:
A way to get php with thread safety was requested again in #69801 which
I've closed as a duplicate so let's continue the conversation here.
The flag to enable thread safety in php 8 and later is now `--enable-zts`
while for earlier versions it's `--enable-maintainer-zts` as mentioned in
the ticket description.
I still don't have answers to the questions I asked [comment:1 above]
about the pros and cons of enabling thread safety. Even
[https://www.php.net/manual/en/faq.obtaining.php#faq.obtaining.threadsafety
php's own FAQ entry] is unhelpful. The only reason it gives for wanting to
enable thread safety is if we're using Apache 2 or IIS 5 or IIS 6 on
Windows. Since we're not on Windows, there must be other reasons.
In #69801, Jonas claimed that using HTTP/2 in Apache 2 requires thread
safety. Jonas, if you could refer me to documentation on this topic that
would be great.
There's
[https://www.php.net/manual/en/faq.installation.php#faq.installation.apache2
another php FAQ entry] which says one should not use php with Apache 2
with a threaded [https://httpd.apache.org/docs/current/mpm.html MPM] in
production. It implies that doing so adds complexity and introduces
weaknesses. I gather that a php used with a threaded MPM has to be built
with thread safety, but a php used with a non-threaded MPM should not be
built with thread safety because that would be unnecessary overhead.
Granted, I doubt anybody is using macOS and MacPorts Apache and PHP in
production.
Replying to [comment:3 ryandesign]:
> I'm also concerned about whether this change would affect any of the
modules.
This is the key difficulty in enabling thread safety.
I see that there are some php modules that we don't have in MacPorts yet,
like parallel and pthreads, that require a thread-safe php. Being able to
add ports for these would therefore be a reason in favor of having a
thread-safe php in MacPorts. However, elsewhere I see claims that some
modules, or the libraries they use, are not thread-safe, so they could not
be used in a thread-safe php. If that applies to any of the php modules we
have in MacPorts now, that would be a reason not to convert all MacPorts
php to the thread-safe flavor.
Beyond those module-specific issues, each php version uses a specific
module directory, into which all modules are installed and from which
modules are loaded. For a standard MacPorts install of php83, for example,
it's /opt/local/lib/php83/extensions/no-debug-non-zts-20230831. If I add a
zts variant like this:
{{{#!diff
diff --git a/lang/php/Portfile b/lang/php/Portfile
index 9fed1f53242..bfaee755890 100644
--- a/lang/php/Portfile
+++ b/lang/php/Portfile
@@ -408,6 +408,14 @@ if {[is_sapi_subport]} {
configure.args-append --enable-debug
}
+ variant zts description {Enable thread safety (for running PHP in a
threaded Apache 2 MPM)} {
+ if {[vercmp ${branch} < 8.0]} {
+ configure.args-append --enable-maintainer-zts
+ } else {
+ configure.args-append --enable-zts
+ }
+ }
+
if {[vercmp ${branch} <= 5.3]} {
variant suhosin description {Add Suhosin patch} {
pre-fetch {
}}}
and install php83 with it, then `non-zts` in module directory name changes
to `zts`. This zts php83 won't be able to find any of the modules that
were built for a non-zts php83. And it's not just a matter of the
directory being different arbitrarily; the modules are actually compiled
differently. If I naively try to symlink no-debug-zts-20230831 to no-
debug-non-zts-20230831 then modules fail to load with messages like
`symbol not found in flat namespace (_executor_globals)` or:
{{{
Warning: PHP Startup: <module name>: Unable to initialize module
Module compiled with build ID=API20230831,NTS
PHP compiled with build ID=API20230831,TS
These options need to match
in Unknown on line 0
}}}
So every PHP module port would need a zts variant too and users would need
to keep the variant selection matched between their php modules ports and
their php SAPIs. The same problem happens if you enable a debug build:
`no-debug` in the module directory name changes to `debug`. MacPorts does
already have to deal with this problem because the php SAPI ports already
do offer a debug variant. The php 1.1 portgroup also defines a debug
variant for each module port and adds code that does its best to ensure
that the variant selection (debug or not debug) of the module matches that
of the CLI SAPI. However it is very easy for users to subvert. For
example, install php83 normally, then install a module (for no-debug-non-
zts), then install php83 with the debug variant; now the module you had
installed is the wrong flavor. So we could certainly do the same for zts
by adding this to the portgroup:
{{{#!diff
diff --git a/_resources/port1.0/group/php-1.1.tcl
b/_resources/port1.0/group/php-1.1.tcl
index 235ab606cf9..e971bdf568f 100644
--- a/_resources/port1.0/group/php-1.1.tcl
+++ b/_resources/port1.0/group/php-1.1.tcl
@@ -406,6 +406,14 @@ proc php.add_port_code {} {
ui_error "${subport} cannot be installed with the debug
variant because ${php} is installed without the debug variant."
return -code error "incompatible variant selection"
}
+ set php_zts_variant ![regexp {/[^/]+-non-zts-[^/]+$}
${php.extension_dir}]
+ if {${php_zts_variant} && ![variant_isset zts]} {
+ ui_error "${subport} cannot be installed without the zts
variant because ${php} is installed with the zts variant."
+ return -code error "incompatible variant selection"
+ } elseif {[variant_isset zts] && !${php_zts_variant}} {
+ ui_error "${subport} cannot be installed with the zts variant
because ${php} is installed without the zts variant."
+ return -code error "incompatible variant selection"
+ }
foreach dir ${php.build_dirs} {
ui_debug "Generating configure script in [file tail ${dir}]"
system -W ${dir} "${php.ize}"
}}}
But it isn't that helpful. It only takes effect at pre-configure time --
in other words, it does not take effect when using MacPorts-provided
binaries. And it only checks the CLI SAPI; when you install a module,
MacPorts has no idea which other SAPI you might eventually want to use
with it so it can't check it.
The way out of all of those problems would be to use subports instead of
variants. That would have the added bonus of making binaries of debug and
zts and debug+zts flavors available. But I'm not sure what we should call
those subports.
Does anybody know how Linux distributions are handling this? Are there any
that offer only thread-safe php, or any that offer both? If any offer
both, what is their naming convention to differentiate them?
The one problem that subports still don't solve is how to identify the
modules and libraries that aren't thread-safe. I don't know what happens
if you try to use a module or library that isn't thread-safe in a php SAPI
built with thread safety. Does it crash immediately? Or does it corrupt
data or have other unpredictable behavior?
--
Ticket URL: <https://trac.macports.org/ticket/38293#comment:4>
MacPorts <https://www.macports.org/>
Ports system for macOS
More information about the macports-tickets
mailing list