php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47566 PCNTL Waitpid exit status incorrect
Submitted: 2009-03-04 21:59 UTC Modified: 2009-05-26 14:03 UTC
From: james at jamesreno dot com Assigned:
Status: Closed Package: PCNTL related
PHP Version: 5.2.9 OS: linux-2.6
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: james at jamesreno dot com
New email:
PHP Version: OS:

 

 [2009-03-04 21:59 UTC] james at jamesreno dot com
Description:
------------
The $status exitcode returned by pcntl_waitpid() is incorrectly casted resulting in an invalid number being returned.

I believe the int is converted to a long in ext/pcntl/pcntl.c, resulting in an invalid integer being returned to the parent.

        zval *z_status = NULL;
        int status;
        convert_to_long_ex(&z_status);
        status = Z_LVAL_P(z_status);
        child_id = waitpid((pid_t) pid, &status, options);
        Z_LVAL_P(z_status) = status;

z_status is a long, but status is an int...


Reproduce code:
---------------
<?
$pid = pcntl_fork();
if ($pid == -1) {
 echo "Unable to fork";
 exit;
} elseif ($pid) {
 $epid = pcntl_waitpid(-1,$status);
 echo "PARENT: {$pid}/{$epid} exited {$status}\n";
 exit(128);
} else {
 echo "CHILD: Exiting with exit code 128\n";
 exit(128);
}
?>

Expected result:
----------------
[james@localhost ~]$ php test.php
CHILD: Exiting with exit code 128
PARENT: 7598/7598 exited 128
[james@localhost ~]$ echo $?
128
[james@localhost ~]$


Actual result:
--------------
[james@localhost ~]$ php test.php
CHILD: Exiting with exit code 128
PARENT: 7598/7598 exited 32768
[james@localhost ~]$ echo $?
128
[james@localhost ~]$

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-03-05 20:54 UTC] james at jamesreno dot com
exit(254);

$pid = pcntl_waitpid(-1,$status);

if (pcntl_wifexited($status)) {
 $status = pcntl_wexitstatus($status);
 echo $status;
}

Then why is $status, -2 rather than '254'?

This method does not seem work *properly* either...
 [2009-05-26 04:47 UTC] james at jamesreno dot com
Not bogus.... see below:

Its obviously not returning properly:
   1.      while (($pid=pcntl_waitpid(-1,$status,WNOHANG))>0) {
   2.       echo "RAW: {$status}\n";
   3.       var_dump(pcntl_wifexited($status));
   4.        var_dump(pcntl_wexitstatus($status));
   5.       var_dump(pcntl_wifsignaled($status));
   6.        var_dump(pcntl_wtermsig($status));
   7.       var_dump(pcntl_wifstopped($status));
   8.        var_dump(pcntl_wstopsig($status));
   9.       echo "END RAW: {$status}\n";
  10.      }
  11.       
  12.      RAW: 65280
  13.      pcntl_wifexited   == bool(true)  => pcntl_wexitstatus == int(-1)
  14.      pcntl_wifsignaled == bool(false) => pcntl_wtermsig    == int(0)
  15.      pcntl_wifstopped  == bool(false) => pcntl_wstopsig    == int(255)
  16.      END RAW: 65280
  17.
  18.  
  19.      RAW: 65280
  20.      bool(true)
  21.      int(-1)
  22.      bool(false)
  23.      int(0)
  24.      bool(false)
  25.      int(255)
  26.      END RAW: 65280

Guess ill be hax0ring the code to make it work properly.

seems the same on PHP 5.3.0-RC2
 [2009-05-26 05:27 UTC] james at jamesreno dot com
/* {{{ proto int pcntl_wexitstatus(int status)
   Returns the status code of a child's exit */
PHP_FUNCTION(pcntl_wexitstatus)

The function definition says it returns an INT, as it SHOULD -- exit codes can not be negative! and are in the range of 0-255 (8 bits) on posix systems. (iirc).


-- HOWEVER --

Php actually returns:
        status_word = (int) Z_LVAL_PP(status);
        /* WEXITSTATUS only returns 8 bits so we *MUST* cast this to signed char
           if you want to have valid negative exit codes */

        RETURN_LONG((signed char) WEXITSTATUS(status_word));

It should NOT, it should not cast it to a (signed char)


So if you actually want the right result in your code :(
In php-5.2.9/ext/pcntl/pcntl.c line 379

Change:
        RETURN_LONG((signed char) WEXITSTATUS(status_word));
to:
        RETURN_LONG(WEXITSTATUS(status_word));
 [2009-05-26 14:03 UTC] lbarnaud@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 17:01:58 2024 UTC