Skip to content

PHP gRPC extension: assert() on exec() #23477

@tony2001

Description

@tony2001

Problem
PHP with gRPC enabled is unable to execute other binaries using simple exec() or popen() calls.
In error log I can see the following errors:

[14-Jul-2020 19:30:40] WARNING: [pool www] child 6 said into stderr: "php-fpm: pool www: /tmp/pear/temp/grpc/src/core/lib/gprpp/ref_counted.h:137: void grpc_core::RefCount::RefNonZero(const grpc_core::DebugLocation&, const char*): Assertion `prior > 0' failed."
[14-Jul-2020 19:30:42] WARNING: [pool www] child 7 said into stderr: "php-fpm: pool www: /tmp/pear/temp/grpc/src/core/lib/gprpp/ref_counted.h:137: void grpc_core::RefCount::RefNonZero(const grpc_core::DebugLocation&, const char*): Assertion `prior > 0' failed."

The first exec() call succeeds, but after that all exec() calls return empty result and I get an error message in the error log for each request to the script.
That happens even though both grpc.enable_fork_support and grpc.poll_strategy are used in php.ini

Versions
I'm using latest PHP gRPC version: 1.30.0 and tried several PHP versions: 7.4.5, latest 7.4-git, 7.2.
For some obscure reason I'm unable to reproduce the issue in my test environment, while I can easily reproduce it in production env (PHP 7.4.5) and using official docker containers (running PHP 7.2).

OS: OpenSuse, SLES, whatever Ubuntu version is used in official containers
gcc version 7.5.0

Steps to reproduce

  1. Run example node-server:
    docker run -d -p 9090:9090 --name node-server grpcweb/node-server
  2. Add exec() call to the client.php:
diff --git a/examples/php/echo/client.php b/examples/php/echo/client.php
index b482992871..8228f7dba2 100644
--- a/examples/php/echo/client.php
+++ b/examples/php/echo/client.php
@@ -19,6 +19,11 @@
 
 require dirname(__FILE__).'/vendor/autoload.php';
 
+$ret = 0;
+$out = [];
+exec("uname", $out, $ret);
+var_dump($out, $ret);
+
 $client = new Grpc\Gateway\Testing\EchoServiceClient('node-server:9090', [
     'credentials' => Grpc\ChannelCredentials::createInsecure(),
 ]);
  1. Don't forget to enable fork support, otherwise gRPC will hang the PHP process indefinitely:
diff --git a/examples/php/echo/fpm.Dockerfile b/examples/php/echo/fpm.Dockerfile
index 6e2df8b013..582e6d25c5 100644
--- a/examples/php/echo/fpm.Dockerfile
+++ b/examples/php/echo/fpm.Dockerfile
@@ -37,6 +37,10 @@ COPY --from=grpc-base \
 
 RUN docker-php-ext-enable grpc
 
+RUN echo '\
+grpc.enable_fork_support=1\n\
+grpc.poll_strategy=epoll1\n\
+' >> /usr/local/etc/php/conf.d/docker-php-ext-grpc.ini
 
 WORKDIR /var/www/html
 
  1. Build FPM container:
    docker build -t grpc-php/fpm -f ./fpm.Dockerfile .
    and run it:
    docker run -it --rm --link node-server:node-server -p 9000:9000 --name fpm grpc-php/fpm

  2. Run Nginx container
    docker run -it --rm -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro --link fpm:fpm -p 80:80 nginx:1.17.4

Any request to http://localhost/index.php results in the mentioned error.

The same code (as in "gRPC loaded + exec()", since we're not using a demo node-server apparently) results in SIGABRT and a core dump in my production environment, which is quite a problem.

I'm still trying to reproduce the issue using my test environment, though.
Of course, I'm ready to provide any kind of additional info.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions