0

Sometimes I have a long task which I don't want the current PHP thread to wait for, and I've done something like the following. Passing data in a session is a little kludgy, but seems to work.

I have another similar application, except file1.php is not being accessed by the user's client, but by another server, and the user is only accessing the other server. As such, a session cookie will not be available to the session_start() in file1.php, and it will have to create a separate session file for each occurrence.

What are other options to pass data to a background worker script? I am not passing huge amount of data, but it still will be 1kb or so.

file1.php

session_start();
$_SESSION['_xfr']=$_POST;
$status=exec($'/usr/bin/php -q /path/to/my/worker.php'.' '.session_id().' >/dev/null &');
echo('Tell client we are done.');

file2.php

session_id($argv[1]);//Set by parent
session_start();
$data=$_SESSION['_xfr'];
//Do some task
user1032531
  • 24,767
  • 68
  • 217
  • 387

2 Answers2

1

You can just send the data via args, as json:

file1.php

$status=exec($'/usr/bin/php -q /path/to/my/worker.php'.' '.json_encode($_POST).' >/dev/null &');
echo('Tell client we are done.');

file2.php

$data=json_decode($argv[1]);
//Do some task
Steve
  • 20,703
  • 5
  • 41
  • 67
  • How much data could be sent as an argument? – user1032531 Jan 16 '15 at 17:01
  • @user1032531 More than 1kb I expect:http://stackoverflow.com/questions/6846263/maximum-length-of-command-line-argument-that-can-be-passed-to-sqlplus-from-lin – Steve Jan 16 '15 at 18:25
1

If the goal is to return a status to a client and continue processing, you might find it easier to simply do something like.

public function closeConnection($body, $responseCode){
    // Cause we are clever and don't want the rest of the script to be bound by a timeout.
    // Set to zero so no time limit is imposed from here on out.
    set_time_limit(0);

    // Client disconnect should NOT abort our script execution
    ignore_user_abort(true);

    // Clean (erase) the output buffer and turn off output buffering
    // in case there was anything up in there to begin with.
    ob_end_clean();

    // Turn on output buffering, because ... we just turned it off ...
    // if it was on.
    ob_start();

    echo $body;

    // Return the length of the output buffer
    $size = ob_get_length();

    // send headers to tell the browser to close the connection
    // remember, the headers must be called prior to any actual
    // input being sent via our flush(es) below.
    header("Connection: close\r\n");
    header("Content-Encoding: none\r\n");
    header("Content-Length: $size");

    // Set the HTTP response code
    // this is only available in PHP 5.4.0 or greater
    http_response_code($responseCode);

    // Flush (send) the output buffer and turn off output buffering
    ob_end_flush();

    // Flush (send) the output buffer
    // This looks like overkill, but trust me. I know, you really don't need this
    // unless you do need it, in which case, you will be glad you had it!
    @ob_flush();

    // Flush system output buffer
    // I know, more over kill looking stuff, but this
    // Flushes the system write buffers of PHP and whatever backend PHP is using
    // (CGI, a web server, etc). This attempts to push current output all the way
    // to the browser with a few caveats.
    flush();
}

Otherwise your options are limited for multithreading in the HTTP server, and shelling out via exec as you are doing it the other way to go ... however, you may want to nohup the command as opposed simply running it as a child process of the current thread.

bubba
  • 3,839
  • 21
  • 25