Opened 12 years ago

Last modified 6 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)

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.

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 6 months ago by ryandesign (Ryan Carsten Schmidt)

Cc: jonaskohl added
Port: php added; php54 removed
Summary: php54 @5.4.12 Enable Thread Safetyphp: 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]} { 
    408408        configure.args-append   --enable-debug
    409409    }
    410410
     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
    411419    if {[vercmp ${branch} <= 5.3]} {
    412420    variant suhosin description {Add Suhosin patch} {
    413421        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 {} { 
    406406            ui_error "${subport} cannot be installed with the debug variant because ${php} is installed without the debug variant."
    407407            return -code error "incompatible variant selection"
    408408        }
     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        }
    409417        foreach dir ${php.build_dirs} {
    410418            ui_debug "Generating configure script in [file tail ${dir}]"
    411419            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?

Note: See TracTickets for help on using tickets.