Search code examples
phpproc-open

PHP - proc_get_status 'running' returning false when javaw executable still running


I am executing javaw with an infinite looping java file using this:

$descriptorspec = array(
                                0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
                                1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
                                2 => array("pipe", "w") // stderr is a file to write to
                        );

 // e.x. $javaCmd = "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 > /dev/null 2>&1 < h.in"
$proc = proc_open($javaCmd, $descriptorspec, $pipes);//, $cwd, $env);
 stream_set_blocking($pipes[0], 0) ;

 $status = proc_get_status($proc);  
 var_dump($status);
  $timeOut = 5;
  $currentSecond = 0;

  while( $currentSecond < $timeOut ) {
        echo '<br/>';
        sleep(1);
        $currentSecond = $currentSecond +1;
        if( ! $status["running"] )
        {
            echo 'process exited before timing out'; // Process must have exited, success!
            return;
        }
        $status = proc_get_status($proc);
        var_dump($status);
  } // end while
  if($currentSecond  == $timeOut)
  {
      // kill KILL KILL!
      exec("taskkill /PID ".$status['pid']);
  }

On the first call to proc_get_status, running attribute returns true. On the second call (one second later) to proc_get_status, running returns false. The application javaw.exe is still running, however ( I call proc_get_status in a while loop that will eventually timeout.)

My goal is to taskkill the program after the timeout has expired. See a similar question here. I am running on Win7 64 bit, PHP 5.3

Var dump on $status: (Note; I tried applying stream_set_blocking($pipes[0], 0) ;, same issue)

Before entering timeout loop:

    array(8) { 
["command"]=> string(157) "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 /dev/null 2>&1 < h.in" 
["pid"]=> int(3264) 
["running"]=> bool(true) 
["signaled"]=> bool(false) 
["stopped"]=> bool(false) 
["exitcode"]=> int(-1) 
["termsig"]=> int(0) 
["stopsig"]=> int(0) 
} 

After first iteration/sleep(1):

    array(8) { 
["command"]=> string(157) "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 /dev/null 2>&1 < h.in" 
["pid"]=> int(3264) 
["running"]=> bool(false) 
["signaled"]=> bool(false) 
["stopped"]=> bool(false) 
["exitcode"]=> int(1) 
["termsig"]=> int(0) 
["stopsig"]=> int(0) 
} 
    process exited before timing out

After testing, it appears that $status['pid'] is different than the pid for javaw.exe under Windows' Resource Monitor.


Solution

  • Although we couldnt pinpoint the issue with proc_get_status returning the incorrect boolean, we were able to find a good work-around (for Unix), using

    if (file_exists("/proc/".$status["pid"])) { // process still running }

    to check if the process was still running or not.

    Here is the full code excerpt:

    $proc = proc_open($javaCmd, array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w")), $pipes);
    
    $status = proc_get_status($proc);
    
    if($status["pid"] === false)
    {
        // Process did not execute correctly
    }
    else
    {
            $timeOut = 0;
            $forceKill = true;
    
            while($timeOut < $timeLimit)
            {
                $timeOut++;
                sleep(1);
                echo 'Timeout is at '.$timeOut.' and timelimit: '.$timeLimit.'<br/>';
    
                if (file_exists("/proc/".$status["pid"])) {
                // process still running
                }
                else
                {
                    echo 'Finished running after '.$timeOut.' seconds<br/>';
                    $forceKill = false;
                    break;
                }
    
            }
            if($forceKill == true)
            {
                echo ' Manual killing pid '.$status['pid'];
                exec("sudo kill ".$status['pid']);
                $runTime = $timeLimit;
            }
    
    
    }