Req #38915 [Com]: Apache: system() (and similar) don't cleanup opened handles of Apache

From: Date: Wed, 27 Dec 2023 15:42:49 +0000
Subject: Req #38915 [Com]: Apache: system() (and similar) don't cleanup opened handles of Apache
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-246137@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=38915&edit=1

 ID:                 38915
 Comment by:         testing at example dot com
 Reported by:        dimmoborgir at gmail dot com
 Summary:            Apache: system() (and similar) don't cleanup opened
                     handles of Apache
 Status:             Analyzed
 Type:               Feature/Change Request
 Package:            Program Execution
 Operating System:   UNIX
 PHP Version:        5.2.2, 4.4.7
 Block user comment: N
 Private report:     N

 New Comment:

555


Previous Comments:
------------------------------------------------------------------------
[2023-12-27 15:42:38] testing at example dot com

555

------------------------------------------------------------------------
[2023-12-27 15:10:55] testing at example dot com

The following patch has been added/updated:

Patch Name: tsSLAueP
Revision:   1703689855
URL:        https://bugs.php.net/patch-display.php?bug=38915&patch=tsSLAueP&revision=1703689855

------------------------------------------------------------------------
[2014-03-14 13:02:42] php at braten dot be

Related To: Bug #15529

------------------------------------------------------------------------
[2013-12-03 17:23:11] brak at gameservers dot com

This same issue appears to happen with PHP-FPM (I am using nginx as the webserver, but that
shouldn't matter).  PHP version 5.4.22 on Linux (CentOS 6.5)


Quick example:
<?php
        $p = popen('/bin/bash -c "sleep 60"','w');
        pclose($p);
?>

Now find the child process (ps aux | grep sleep) and lsof -p XXX -n:

sleep   13443 nobody    0r  FIFO      0,8      0t0 10237775 pipe
sleep   13443 nobody    1u   CHR      1,3      0t0     3920 /dev/null
sleep   13443 nobody    2u   CHR      1,3      0t0     3920 /dev/null
sleep   13443 nobody    4u  IPv4 10236693      0t0      TCP 127.0.0.1:cslistener->127.0.0.1:53151
(ESTABLISHED)
sleep   13443 nobody    9u   REG      0,9        0     3918 [eventpoll]


FD 4 there is the TCP connection from the PHP worker process to the web server.

------------------------------------------------------------------------
[2012-10-31 23:56:34] oliver at realtsp dot com

we solved by passing the forked/exec'd process through a bash shell and closing 
all te file 
descriptors: eg: (note this is for FreeBSD using daemon, but "nohup" should work 
on linux)

daemon /usr/bin/env bash -c 'exec 0<&-; exec 1> /path/to/error/log; exec 2> 
/path/to/stdout/log; 
eval exec {3..255}\>\&-; /usr/bin/env php /path/to/script args...'

Note we find it crucial to redirect and NOT CLOSE STDOUT and STDERR because 
otherwise you will 
never find out if sth is wrong with forked process. You should ensure that they 
exist and are 
writable before forking. 

The trick with eval exec {3..255}\>\&-;  is from here:
http://blog.n01se.net/blog-n01se-net-p-145.html

This works for us in a php-fastcgi situation. the fastcgi-socket and the mysql 
socket are both 
closed successfully. the new process opens its own mysql socket just fine...

I suspect this is similar to what Jeroen's closedexec.c does, but no need for a 
c program. 
Everyone should have bash. 

If you redirect the stdout of above fork command to a file and check the 
contents of that daemon 
gives you nice messages, just append 

 2> /path/to/temp/stderr/file/for/daemon/messages

to the above command.

We have the construction of the fork command wrapped in a simple function, like 
so:

    $exec_cmd = ((php_uname('s') == 'FreeBSD') ? 'daemon' :
'nohup') .                  
// try to 
be OS agnostic, daemon = fork, setguid etc, but don't close stderr with -f         
      ' /usr/bin/env bash -c ' .                                                        
// wrap 
actual call to new php process in a shell (use env!), so                             
      // must escape here in case the already escaped args contain                                  
                                                                                
      // specials chars like single quotes (which the will!)                                        
                                                                                
      escapeshellarg(
        'exec 0<&-; ' .                                                            
    
// close 
STDIN                                                                               
        'exec 1> ' . escapeshellarg($app_log) . '; ' .                       
          
// STDOUT 
> app_log                                                                          
        'exec 2> ' . escapeshellarg($error_log) . '; ' .                     
          
// STDOUT 
> error_log                                                                        
        'eval exec {3..255}\>\&-; ' .                                              
    
// we can 
close all other fds (fastcgi, mysql, etc)..eval trick!                             
        '/usr/bin/env php ' . BASE . $cmd . ' ' .                               
       
// call 
php (with env!) don't rely on shebang or exec perms                                  
        join(' ',                                                                       
// add 
args separated by spaces                                                              
             array_map(function ($arg) { return escapeshellarg($arg); }, $args))        
// after 
escaping them                                                                       
        );


Sorry about the formatting...

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=38915


--
Edit this bug report at https://bugs.php.net/bug.php?id=38915&edit=1


Thread (50 messages)

« previous php.bugs (#246137) next »