Como o DYLD_LIBRARY_PATH pode não ser configurado para processos launchd?

1

O magro

Eu criei o PHP como um módulo do apache (libphp56.so) e o vinculei ao libcurl do MacPorts. No entanto, o httpd falha ao iniciar (via launchd) se libphp56.so é carregado, imprimindo um erro de incompatibilidade de versão da biblioteca.

A gordura

Eu executei o script de configuração do PHP com --with-curl=/opt/local para vinculá-lo a /opt/local/lib/libcurl.4.dylib (fornecido pelo MacPorts). Essa cópia do libcurl é a versão 9.0.0, mas o dyld afirma que a versão 7.0.0 está sendo carregada, que por acaso é a versão do /usr/lib/libcurl.4.dylib. Por enquanto, estou assumindo que o último está sendo carregado.

apachectl chama launchctl para executar o httpd. Se executado diretamente, o httpd carrega libphp56.so e é executado sem erros.

Aqui estão algumas informações relevantes da linha de comando (espaço em branco adicionado para facilitar a leitura):

$ sudo -s
# apachectl configtest
httpd: Syntax error on line 174 of /private/etc/apache2/httpd.conf: 
Cannot load libexec/apache2/libphp56.so into server: 
dlopen(/Library/WebServer/libexec/apache2/libphp56.so, 10): 
Library not loaded: /opt/local/lib/libcurl.4.dylib

Referenced from: /Library/WebServer/libexec/apache2/libphp56.so
Reason: Incompatible library version: libphp56.so requires version 9.0.0 or later, but libcurl.4.dylib provides version 7.0.0

# /usr/sbin/httpd
# ps -ax -O gid | grep /usr/sbin/httpd
 6878     0   ??  Ss     0:00.22 /usr/sbin/httpd
 6901    70   ??  S      0:00.00 /usr/sbin/httpd
 6907     0 s008  S+     0:00.00 grep --color=auto /usr/sbin/httpd
# kill -TERM 6878

# otool -L /opt/local/lib/libcurl.4.dylib | grep libcurl
/opt/local/lib/libcurl.4.dylib:
    /opt/local/lib/libcurl.4.dylib (compatibility version 9.0.0, current version 9.0.0)

# otool -L /usr/lib/libcurl.4.dylib | grep libcurl 
/usr/lib/libcurl.4.dylib:
    /usr/lib/libcurl.4.dylib (compatibility version 7.0.0, current version 8.0.0)

# otool -L /Library/WebServer/libexec/apache2/libphp56.so | grep libcurl
    /opt/local/lib/libcurl.4.dylib (compatibility version 9.0.0, current version 9.0.0)

# echo "x${DYLD_LIBRARY_PATH}x"
xx
# grep -r 'DYLD_.*_PATH' /etc
# launchctl getenv DYLD_LIBRARY_PATH

O launchd.plist para o httpd é bastante básico:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Disabled</key>
    <false/>
    <key>EnvironmentVariables</key>
    <dict>
      <key>XPC_SERVICES_UNAVAILABLE</key>
      <string>1</string>
    </dict>
    <key>KeepAlive</key>
    <dict>
      <key>SuccessfulExit</key>
      <false/>
    </dict>
    <key>Label</key>
    <string>org.apache.httpd</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/sbin/httpd</string>
      <string>-D</string>
      <string>FOREGROUND</string>
    </array>
  </dict>
</plist>

Definindo as variáveis de ambiente de relatório dyld DYLD_PRINT_TO_FILE , DYLD_PRINT_ENV and DYLD_PRINT_LIBRARIES revela conjuntos de launchd DYLD_LIBRARY_PATH e /usr/lib/libcurl.4.dylib é carregado.

# DYLD_PRINT_TO_FILE=~/httpd.log DYLD_PRINT_ENV=1 DYLD_PRINT_LIBRARIES=1 apachectl configtest
# grep -P 'curl|DYLD_' ~/httpd.log
DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log
DYLD_PRINT_LIBRARIES=1
DYLD_PRINT_ENV=1
DYLD_PRINT_LIBRARIES=1
DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log
DYLD_LIBRARY_PATH=/usr/lib
DYLD_PRINT_ENV=1
dyld: loaded: /usr/lib/libcurl.4.dylib
# echo > ~/http.log
# DYLD_PRINT_TO_FILE=~/httpd.log DYLD_PRINT_ENV=1 DYLD_PRINT_LIBRARIES=1 /usr/sbin/httpd -D FOREGROUND
^C
# grep -P 'curl|DYLD_' ~/httpd.log
DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log
DYLD_PRINT_LIBRARIES=1
DYLD_PRINT_ENV=1
dyld: loaded: /opt/local/lib/libcurl.4.dylib
dyld: unloaded: /opt/local/lib/libcurl.4.dylib
dyld: loaded: /opt/local/lib/libcurl.4.dylib

Note que libcurl não é a única biblioteca a sofrer este problema. Durante a solução de problemas, deixei de fora a extensão curl do PHP como parte da compilação e recebi uma mensagem semelhante em relação à libxml.

A (s) pergunta (s)

Como posso desfazer DYLD_LIBRARY_PATH do httpd quando executado via launchd? Quais são as ramificações de segurança?

Soluções tentadas

  • launchctl unsetenv DYLD_LIBRARY_PATH
  • definindo DYLD_LIBRARY_PATH em org.apache.httpd.plist.
  • ter o org.apache.httpd.plist executando um wrapper para o httpd que define DYLD_LIBRARY_PATH

Não soluções

Enquanto eu poderia ligar contra o libcurl do sistema, eu estou procurando uma maneira de executar o PHP com componentes atualizados; ligar /usr/lib/libcurl.4.dylib é apenas um último recurso. Evitar o launchd inteiramente, não incluindo as extensões / bibliotecas PHP afetadas na compilação e substituindo o sistema libcurl também são consideradas não-soluções. Eu quase consideraria ter um invólucro que se movesse.

Informações do sistema

  • SO: Mac OS X 10.10.5 Yosemite.
  • Servidor da Web: Apache 2.4.16
  • PHP 5.6.31
por outis 14.08.2017 / 00:07

0 respostas