[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