Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7550817
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T10:18:51+00:00 2026-05-30T10:18:51+00:00

Background I am writing a simple online judge (a code grading system) using PHP

  • 0

Background

I am writing a simple online judge (a code grading system) using PHP and MySQL. It takes submitted codes in C++ and Java, compiles them, and tests them.

This is Apache running PHP 5.2 on an old version of Ubuntu.

What I am currently doing

I have a php program that loops infinitely, calling another php program by

//for(infinity)
    exec("php -f grade.php");
//...

every tenth of a second. Let’s call the first one looper.php and the second one grade.php. (Checkpoint: grade.php should completely finish running before the “for” loop continues, correct?)

grade.php pulls the earliest submitted code that needs to be graded from the MySQL database, puts that code in a file (test.[cpp/java]), and calls 2 other php programs in succession, named compile.php and test.php, like so:

//...
exec("php -f compile.php");
//...
//for([all tests])
    exec("php -f test.php");
//...

(Checkpoint: compile.php should completely finish running before the “for” loop calling test.php even starts, correct?)

compile.php then compiles the program in test.[cpp/java] as a background process. For now, let’s assume that it’s compiling a Java program and that test.java is located in a subdirectory. I now have

//...
//$dir = "./sub/" or some other subdirectory; this may be an absolute path
$start_time = microtime(true); //to get elapsed compilation time later
exec("javac ".$dir."test.java -d ".$dir." 2> ".$dir
        ."compileError.txt 1> ".$dir."compileText.txt & echo $!", $out);
//...

in compile.php. It’s redirecting the output from javac, so javac should be running as a background process… and it seems like it works. The $out should be grabbing the process id of javac in $out[0].

The real problem

I want to stop compiling if for some reason compiling takes more than 10 seconds, and I want to end compile.php if the program stops compiling before 10 seconds. Since the exec("javac... I called above is a background process (or is it?), I have no way of knowing when it has completed without looking at the process id, which should have been stored in $out earlier. Right after, in compile.php, I do this with a 10 second loop calling exec("ps ax | grep [pid].*javac"); and seeing if the pid still exists:

//...
$pid = (int)$out[0];
$done_compile = false;

while((microtime(true) - $start_time < 10) && !$done_compile) {

    usleep(20000); // only sleep 0.02 seconds between checks
    unset($grep);
    exec("ps ax | grep ".$pid.".*javac", $grep);

    $found_process = false;

    //loop through the results from grep
    while(!$found_process && list(, $proc) = each($grep)) {
        $boom = explode(" ", $proc);
        $npid = (int)$boom[0];

        if($npid == $pid)
            $found_process = true;
    }
    $done_compile = !$found_process;
}

if(!done_compile)
    exec("kill -9 ".$pid);
//...

… which doesn’t seem to be working. At least some of the time. Often, what happens is test.php starts running before the javac even stops, resulting in test.php not being able to find the main class when it tries to run the java program. I think that the loop is bypassed for some reason, though this may not be the case. At other times, the entire grading system works as intended.

Meanwhile, test.php also uses the same strategy (with the X-second loop and the grep) in running a program in a certain time limit, and it has a similar bug.

I think the bug lies in the grep not finding javac‘s pid even when javac is still running, resulting in the 10 second loop breaking early. Can you spot an obvious bug? A more discreet bug? Is there a problem with my usage of exec? Is there a problem with $out? Or is something entirely different happening?

Thank you for reading my long question. All help is appreciated.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T10:18:52+00:00Added an answer on May 30, 2026 at 10:18 am

    I just came up with this code that will run a process, and terminate it if it runs longer than $timeout seconds. If it terminates before the timeout, it will have the program output in $output and the exit status in $return_value.

    I have tested it and it seems to work well. Hopefully you can adapt it to your needs.

    <?php
    
    $command = 'echo Hello; sleep 30'; // the command to execute
    $timeout = 5; // terminate process if it goes longer than this time in seconds
    
    $cwd = '/tmp';  // working directory of executing process
    $env = null;    // environment variables to set, null to use same as PHP
    
    $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("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
    );
    
    // start the process
    $process    = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
    $startTime  = time();
    $terminated = false;
    $output     = '';
    
    if (is_resource($process)) {
        // process was started
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // Any error output will be appended to /tmp/error-output.txt
    
        // loop infinitely until timeout, or process finishes
        for(;;) {
            usleep(100000); // dont consume too many resources
    
            $stat = proc_get_status($process); // get info on process
    
            if ($stat['running']) { // still running
                if (time() - $startTime > $timeout) { // check for timeout
                    // close descriptors
                    fclose($pipes[1]);
                    fclose($pipes[0]);
                    proc_terminate($process); // terminate process
                    $return_value = proc_close($process); // get return value
                    $terminated   = true;
                    break;
                }
            } else {
                // process finished before timeout
                $output = stream_get_contents($pipes[1]); // get output of command
                // close descriptors
                fclose($pipes[1]);
                fclose($pipes[0]);
    
                proc_close($process); // close process
                $return_value = $stat['exitcode']; // set exit code
                break;
            }
        }
    
        if (!$terminated) {
            echo $output;
        }
    
        echo "command returned $return_value\n";
        if ($terminated) echo "Process was terminated due to long execution\n";
    } else {
        echo "Failed to start process!\n";
    }
    

    References: proc_open(), proc_close(), proc_get_status(), proc_terminate()

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Background I am writing and using a very simple CGI-based (Perl) content management tool
I come from an ASP .Net background. I am now writing a Java program
BACKGROUND I'm writing a method that will (eventually) take as input a System.Data.DataTable and
I am writing simple webapp in Java (for educational purpuses only) which allows admin
I am writing a simple little piece of code to draw pixels wherever the
I'm writing a very simple Java Game. Let me describe it briefly: There are
I'm writing a simple program using SDL, but I'm running into a strange problem.
I am writing a simple application in Java that does some particle simulation on
I'm writing some wxWidgets samples for educational purposes. My problem is simple: I'm using
I am writing a simple HTML email design editor in PHP and also show

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.