Opened 12 years ago
Last modified 7 months ago
#38293 new enhancement
php: Enable Thread Safety
Reported by: | waltersonntag@… | Owned by: | ryandesign (Ryan Carsten Schmidt) |
---|---|---|---|
Priority: | Normal | Milestone: | |
Component: | ports | Version: | 2.1.3 |
Keywords: | Cc: | jonaskohl (Jonas Kohl) | |
Port: | php |
Description
I am trying to get php54 installed with "Thread Safety => enabled".
I am able to get "Thread Safety" enabled by compiling php 5.4.12 from the php.net source, by appending configure arguments:
- --enable-maintainer-zts
- --with-tsrm-pthreads
I have been unsuccessful in enabling "Thread Safety" by editing the php/Portfile. I have tried to add this:
- configure.args-append --enable-maintainer-zts
- configure.args-append --with-tsrm-pthreads
.. and also tried to append this to the main "configure.args" declaration:
- --enable-maintainer-zts \
- --with-tsrm-pthreads
However, neither of those methods seemed to actually compile php54 with "Thread Safety" enabled.
Perhaps I am just doing it wrong but any help with this issue would be greatly appreciated.
Change History (4)
comment:1 Changed 12 years ago by ryandesign (Ryan Carsten Schmidt)
comment:2 Changed 12 years ago by jmroot (Joshua Root)
Owner: | changed from macports-tickets@… to ryandesign@… |
---|---|
Port: | php54 added |
comment:3 Changed 11 years ago by ryandesign (Ryan Carsten Schmidt)
Can you provide some answers to the questions I asked above?
I'm also concerned about whether this change would affect any of the modules.
comment:4 Changed 7 months ago by ryandesign (Ryan Carsten Schmidt)
Cc: | jonaskohl added |
---|---|
Port: | php added; php54 removed |
Summary: | php54 @5.4.12 Enable Thread Safety → php: Enable Thread Safety |
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 above about the pros and cons of enabling thread safety. Even 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 another php FAQ entry which says one should not use php with Apache 2 with a threaded 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 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:
-
lang/php/Portfile
diff --git a/lang/php/Portfile b/lang/php/Portfile index 9fed1f53242..bfaee755890 100644
a b if {[is_sapi_subport]} { 408 408 configure.args-append --enable-debug 409 409 } 410 410 411 variant zts description {Enable thread safety (for running PHP in a threaded Apache 2 MPM)} { 412 if {[vercmp ${branch} < 8.0]} { 413 configure.args-append --enable-maintainer-zts 414 } else { 415 configure.args-append --enable-zts 416 } 417 } 418 411 419 if {[vercmp ${branch} <= 5.3]} { 412 420 variant suhosin description {Add Suhosin patch} { 413 421 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:
-
_resources/port1.0/group/php-1.1.tcl
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 b proc php.add_port_code {} { 406 406 ui_error "${subport} cannot be installed with the debug variant because ${php} is installed without the debug variant." 407 407 return -code error "incompatible variant selection" 408 408 } 409 set php_zts_variant ![regexp {/[^/]+-non-zts-[^/]+$} ${php.extension_dir}] 410 if {${php_zts_variant} && ![variant_isset zts]} { 411 ui_error "${subport} cannot be installed without the zts variant because ${php} is installed with the zts variant." 412 return -code error "incompatible variant selection" 413 } elseif {[variant_isset zts] && !${php_zts_variant}} { 414 ui_error "${subport} cannot be installed with the zts variant because ${php} is installed without the zts variant." 415 return -code error "incompatible variant selection" 416 } 409 417 foreach dir ${php.build_dirs} { 410 418 ui_debug "Generating configure script in [file tail ${dir}]" 411 419 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?
Are you requesting that we add a variant for thread safety to the php53/php54/php55 ports? Or perhaps that we enable it always? What is the significance of enabling thread safety? Are there any negative consequences?
Certainly, if using that argument on the command line works, then putting it in the portfile in the right place will work too. Either you didn't put it in the right place in the portfile, or you received a pre-compiled binary from our server; if the latter, avoid that by using the
-s
switch.