How Do I load pthreads extension in CLI? - php

I have built both php and Apache from source on MAC OSX 10.11.
I have been having trouble loading pthreads extension in CLI.. I misunderstood how to load it and now I do not truly understand what should I do.
Here is what I have done so far.
I configured php with the following command:
'./configure'
'--prefix=/Users/username/Terminal/WebServer'
'--with-apxs2=/Users/username/Terminal/WebServer/bin/apxs'
'--enable-maintainer-zts'
'--enable-pthreads=shared'
'--enable-debug'
'--with-tsrm-pthreads'
'--with-config-file-path=/Users/username/Terminal/WebServer/ini'
'--enable-cli'
Apache's loaded Modules:
Compiled in modules:
core.c
mod_so.c
http_core.c
worker.c
So, in /Users/username/Terminal/WebServer/ini directory I created php-cli.ini file and added extension=pthreads.so line, then I ran php -m command, the following is the output:
[PHP Modules]
Core
ctype
date
dom
fileinfo
filter
hash
iconv
json
libxml
pcre
PDO
pdo_sqlite
Phar
posix
<strong>pthreads</strong>
Reflection
session
SimpleXML
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
[Zend Modules]
I restarted Apache and opened index.php file which has phpinfo() in it.
Notable information
Configuration File (php.ini) Path => /Users/username/Terminal/WebServer/ini
Loaded Configuration File => /Users/username/Terminal/WebServer/ini/php.ini
Scan this dir for additional .ini files => (none)
Additional .ini files parsed => (none)
Thread Safety => Enabled
phpinfo() doens't include pthreads module information and I don't know whether it should or not.
at this point I open test.php file which includes the following pthreads script:
<?php $thread = new class extends Thread {
public function run() {
echo "Hello World\n";
}
};
$thread->start() && $thread->join();
?>
and the output through apache is:
Fatal error: Class 'Thread' not found in /Users/username/Sites/test.php on line 1
When I run the following command on Terminal
$ php /Users/username/Sites/test.php
The output is : Hello World
So the question is how do I load pthreads extension in CLI properly ?

You already have the desired result, but don't seem to know why ...
The key parts of your configuration are:
configure options
If PHP is being built with Apache DSO SAPI, you must use --enable-pthreads=shared, this causes the build process to create a DSO (shared object, dll in windows speak) from the pthreads library, rather than statically linking pthreads into the Apache DSO.
php.ini configuration
From the PHP manual:
If php-SAPI.ini exists (where SAPI is the SAPI in use, so, for example, php-cli.ini or php-apache.ini), it is used instead of php.ini. The SAPI name can be determined with php_sapi_name().
Having built pthreads shared (pthreads.so), we can simply create php-cli.ini in the same path as php.ini and add extension=pthreads.so to it.
What you have works, however, it's not ideal; You don't really want Apache to use a PHP interpreter that has the overhead of ZTS.
Ideally, you will want to build and install PHP twice:
First Build
configure --with-apxs=... --disable-pthreads --prefix=/system/prefix --with-config-file-path=/system/prefix/etc ...
Replace /system/prefix/ with sensible system prefix like /usr/ ...
When you make install this build, you will create the ideal installation for Apache, which includes a non-thread safe PHP binary at /system/prefix/bin/php, with all related scripts (pecl, phpize, php-config etc.) in /system/prefix/bin.
Second Build
Before this build you need to make clean (if you are using a release tarball), or vcsclean (if you are using local git repository).
configure --enable-maintainer-zts --enable-pthreads=static --prefix=/special/prefix --with-config-file-path=/special/prefix/etc ...
Replace /special/prefix/ with sensible special prefix like /opt/, do not use the same prefix as the first build ...
When you make install the first installation is not touched, instead a new installation is created without support for Apache, but with support for pthreads built statically into the binary (configuration free).
The binary will be at /special/prefix/bin/php with all related scripts in /special/prefix/bin.
Wiring Builds Together
If both builds require the same PECL extensions with the exception of pthreads, you can use the same --with-config-file-scan-dir configure switch for both builds.
If you are really brave, you could use the same --with-config-file-path switch too, but this might have undesired results.
Editing include_path for both builds will also help.

Related

Module pcntl already loaded in Unknown on line 0 - Apache x Cli

I'm getting this PHP Warning:
Module 'pcntl' already loaded in Unknown on line 0
But it is only enabled for Apache. Enabled it on /etc/php/7.2/apache2/conf.d/20-pcntl.ini:
extension=pcntl.so
I don't have it enabled on CLI. Checked with:
I don't have a /etc/php/7.2/cli/conf.d/20-pcntl.ini file
Grep command grep -R extension=pcntl.so /etc/php/7.2 only returns the file on apache2 folder
If I disable this extension on Apache's .ini, it won't load on Apache but loads on Cli.
If I enable this extension on Apache's .ini, I get the module already loaded warning.
I'm need to enable PCNTL on Apache to use Spatie\Async library.
It's a Ubuntu 14 server.
Sometimes extensions are compiled into PHP rather than loaded as separate modules. Before fiddling with the PHP.ini files, you should probably run a quick PHP script to see what modules are loaded:
<?php
var_dump(get_loaded_extensions());
You should also beware of PHP directives like disable_functions which may be disabling the pcntl functions. On my Ubuntu workstation, the pcntl functions are disabled with this directive:
/etc/php5/apache2/php.ini:disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority
I suggest you try a broader grep search to see if pcntl gets mentioned in other places:
grep -ir pcntl.so /etc/php/7.2
I don't have a /etc/php/7.2/cli/conf.d/20-pcntl.ini file
That seems a bit weird to me. You might try searching for more php.ini files there:
sudo find /etc -name "php.ini"
You should also check to make sure that you aren't running a different PHP from the command line than you are with apache. Under certain circumstances (which regrettably happen more often that you might think) your CLI PHP is different than your Apache PHP. This article discusses that issue in more detail.
If I disable this extension on Apache's .ini, it won't load on Apache but loads on Cli.
That actually sounds reasonable to me. If I had to guess, I would say that the wise Ubuntu/Debian package manager folks decided it would be unwise to allow pcntl_x functions to run in an apache environment, especially given this stark and ancient warning. I don't recall if that warning is outdated now or not. I would refer you to this other thread where I asked some related questions and was told I should use PHP-FPM with apache in event mode.
All that said, I have had some tremendous success writing "multithreaded" applications in PHP (technically not multithreaded but rather multiprocessing) using pcntl_fork and posix_setsid and the like.
To summarize, I'm guessing that PCNTL is already loaded both on apache and cli and the wise Ubuntu devs probably disabled the pcntl functions in the php.ini.
I know this is long after the original post, but I faced a similar problem. I'm working on a AWS Linux AMI and pnctl seems to be pre-installed into php-cli (not loaded via php.ini)
The problem is Spatie async checks your PHP Runtime (PHP-FPM) to see if the pnctl and posix modules are loaded, which by default aren't even though they are available in php-cli which it actually uses when you create Spatie Async Pools.
My solution was to actually modify the php-fpm service to run with extension=pnctl.so
systemctl edit php-fpm
It will create an override file in /etc/systemd/system/
Modify the file by changing
ExecStart=/usr/sbin/php-fpm --nodaemonize to ExecStart=/usr/sbin/php-fpm -d extension=pctnl.so--nodaemonize and save that
Then restart your nginx and php-fpm services and pnctl should be active for PHP-FPM

Understanding why PHP does not load an extension

I've compiled PHP from source (5.5.7), as well as the memcached extension (2.2.0). I've installed memcached and the extension is correctly installed in /usr/local/lib/php/extensions/no-debug-non-zts-20121212 (there is the memcached.so file) and my php -i tells me that the extension directory is correct : extension_dir => /usr/local/lib/php/extensions/no-debug-non-zts-20121212
PHP runs correctly simple files, but when I load an app using memcached, the PHP error log file tells me only PHP Fatal error: Class 'Memcached' not found but I have no more details.
When I run php -m, there is no memcached module listed.
How can I find out why memcached is not loaded by PHP ?
For the record, it's not enough that there is a memcached.so file in the extension_dir of PHP. PHP also needs to extension to be explicitly loaded in the php.init file.
Solved it with the following command
echo 'extension=memcache.so' >> /usr/local/lib/php.ini

php-fpm doesn't load kafka extension while php cli does

I compile php kafka extension as this link says.
I can use Kafka Class in php cli mode but get an Class 'Kafka' not found error in php-fpm(web request) mode.
php --info | grep kafka indicate the extension is present while phpinfo in html indicate the extension the is absent.
I can confirm from the phpinfo page that php-fpm and php-cli use the same php.ini.
So, How can I spot where the problem is ?
php version : 5.5.13
php-fpm version : 5.5.13
I find the answer.
The Class 'Kafka' not found error in php-fpm mode is caused by php-fpm unable to load Kafka extension. Although I add extension=kafka.so in php.ini. But some error occured while loading the extension.
I found the reason by use dl to load the extension manually, and get error in the response. Why does the php-fpm keep silent while some error occured in the process of loading extension. Maybe I missed some configuration?
Anyway, the reason is found. Php-fpm can't load librdkafka while load extension kafka. The librdkafka is in the dir /usr/local/lib, which is not in the ld search path in red-hat. Check /etc/ld.so.conf for your search path.
Add /usr/local/lib to /etc/ld.so.conf and run ldconfig solve the problem.
The reason why cli mode worked is because the variable $LD_LIBRARY_PATH="/usr/local/lib".
For more info about the loading process, check this link
The list of directories to be searched is stored in the file /etc/ld.so.conf. Many Red Hat-derived distributions don't normally include /usr/local/lib in the file /etc/ld.so.conf. I consider this a bug, and adding /usr/local/lib to /etc/ld.so.conf is a common ``fix'' required to run many programs on Red Hat-derived systems.
Searching all of these directories at program start-up would be grossly inefficient, so a caching arrangement is actually used. The program ldconfig(8) by default reads in the file /etc/ld.so.conf, sets up the appropriate symbolic links in the dynamic link directories (so they'll follow the standard conventions), and then writes a cache to /etc/ld.so.cache that's then used by other programs. This greatly speeds up access to libraries. The implication is that ldconfig must be run whenever a DLL is added, when a DLL is removed, or when the set of DLL directories changes; running ldconfig is often one of the steps performed by package managers when installing a library. On start-up, then, the dynamic loader actually uses the file /etc/ld.so.cache and then loads the libraries it needs.
The install guide in github menthioned about run ldconfig, but red-hat has the special situatiion the lib dir is not in the ld config file.

I don't see the extensions directives in php.ini, yet the extensions are loaded

So i have a php.ini for our vps where none of the extensions are defined(ie "extension=php_curl.so"), yet when i look at phpinfo() on the webpage, i see all our modules/extensions are loaded(ie, curl, mbstring, imagick etc). Where/how else can those extensions be loaded?
EDIT
Also in EashApache, in the php extensions section of your build/profile, it shows all the available extensions(enabled/or not).
I'm certain theres a master php.ini of some sort some where on the vps, or maybe the server the vps is on where all default php configurations are loaded by default.
Extensions can be compiled as shared objects which you load via an extension=... directive or (but shouldn't imho) via dl().
Extensions can also be compiled into the php core. Then they are available without further "commands".
phpinfo() gives you information about the php core in its Configure Command section, e.g.
--with-pdo-oci=c:\php-sdk\oracle\x86\instantclient_12_1\sdk,shared
--with-mcrypt
The pdo_oci module is build as a shared object/dll while the mcrypt module is built into the php core.
Extensions in directory "extension_dir" (definined in php.ini) are automatically included.

What does --with-extension in php compiling do?

I've just learnt how to compile php modules and things but I'm unsure of something.
My OS X comes with php 5.4.17 and it seems to have various extensions in it without any .sos anywhere (pdo_sqlite, pdo_mysql, curl etc)
If I compile php --with-extension, is that extension then built into the php binaries without need for adding in php? Or something similar.
E.g. I compiled pdo_sqlite and pdo_mysql and it warned that I was trying to include them twice. I unincluded them from php.ini and checked phpinfo() and they were already enabled and nowhere on my system.
I can only assume that the configure command put them in the binaries.
Is this right?
check your phpinfo() output page, whether you have this:
Scan this dir for additional .ini files
Additional .ini files parsed
most probably pdo_sqlite and pdo_mysql are already defined in the Additional .ini files parsed
after running ./configure --with-extension, run grep Configured config.log, you will see the actual configure options used
--with-extension enables the specified extension in your custom php build.
For example
--with-apx2=/usr/local/apache2/bin/apxs
enables apache2 server installed at location /usr/local/apache2/bin/apxs

Categories