Hi, I logged "Bug #17538 proc_close() doesn't return exit value of process" a little while a ago, full details are at http://bugs.php.net/bug.php?id=17538 obviously, but the short summary is that proc_close() doesn't return the exit value of the process, like it's meant to. The bug I logged has an example script and stuff.
Anyway, I needed a fix soon, so I've had a poke around in the PHP source myself, and I have basically got pretty close to a fix. I deliberated for a little bit about whether I should try and make a patch, or log more info on the bug, but I decided that posting to the list was best, because I don't have a magic wand fix, rather some *very* relevant info that a PHP developer will be able to use to create a proper fix. Ok, so, all the problems I found are in ext/standard/exec.c (CVS version of course). This is the offending code: # if HAVE_SYS_WAIT int wstatus; pid_t child, wait_pid; child = (pid_t)rsrc->ptr; do { wait_pid = waitpid(child, &wstatus, 0); } while (wait_pid == -1 && errno = EINTR); if (wait_pid == -1) FG(pclose_ret) = -1; else FG(pclose_ret) = wstatus; # else FG(pclose_ret) = -1; # endif Firstly, the gdb was showing me that code inside here wasn't getting executed (waitpid() wasn't getting run). It turns out that there is no HAVE_SYS_WAIT in php_config.h, but there is a HAVE_SYS_WAIT_H. I imagine that perhaps it should be HAVE_SYS_WAIT_H? Anyway, that was what was causing the code not to be run. So, for the purposes of my experimentation, I just deleted the # if # else and # endif lines (and the FG() line between else and endif) so that the code could run, since clearly this is the code that sets pclose_ret, which is in turn the number returned by proc_close(). That was the first problem. I'm sure someone more knowledgeable about the PHP source will know if it's actually meant to be HAVE_SYS_WAIT_H, or something else. So, with that removed, I tried to compile, and the } while (wait_pid == -1 && errno = EINTR); line gave me an "invalid lvalue in assignment" compiler error. Changing to "errno == EINTR" fixed that, but I'm not sure if it's meant to be == or not, or what's meant to be happening. But, I took a punt at ==, and it compiled. Then, I tried running some programs through proc_open() and proc_close(), but php was mangling the return values. The line: FG(pclose_ret) = wstatus; should be FG(pclose_ret) = WEXITSTATUS(wstatus); see "man waitpid" for details, basically wstatus contains more than just the exit code, and WEXITSTATUS() returns the relevant exit status number. So, I compiled again, and it worked! I ended up with: int wstatus; pid_t child, wait_pid; child = (pid_t)rsrc->ptr; do { wait_pid = waitpid(child, &wstatus, 0); } while (wait_pid == -1 && errno == EINTR); if (wait_pid == -1) FG(pclose_ret) = -1; else FG(pclose_ret) = WEXITSTATUS(wstatus); Now, it would be great if a PHP developer could apply this, or something along these lines, to the source tree to make proc_close() work (and close my bug!). As I say, I'm no PHP developer, nor even a particularly good C programmer, so there may well be other things to consider when applying a fix that I've missed, but this worked for me :) Thanks, KimS -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php