samedi 18 juin 2016

Why Does This PHP Hang The Page?


On a page I have buttons to launch and cancel tasks to be performed in PHP on the server side. While these PHP tasks are running the user cannot navigate away from the page, it just hangs up until the job is done. I'm trying to find what's causing the synchronous behavior.

Jquery:

$(document).ready(function() 
{
  var id = 0;

  $('#tool-execute-btn').click(function()
  {
    // Pull data from page

    var last_response_len = false;
    $.ajax( 
    {
      xhrFields: 
      {
        onprogress: function(e)
        {
          var this_response, response = e.currentTarget.response;

          if(last_response_len === false)
          {
            this_response = response;
            last_response_len = response.length;
          }
          else
          {
            this_response = response.substring(last_response_len);
            last_response_len = response.length;
          }

          // Get the data from the stream (backend php)
          $('#tool-output-area').append(this_response + '<br>');
      }
    },
    method: 'POST',
    url: 'run-tool.php', // See block below
    data:
    { 
        // Data from page
    }
  }) // ... Continue

The backend processing PHP page:

/* Setup the page so I can stream the content
 * line by line back to the user */
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

/* Set Maximum Execution Time By Plan */
ini_set('max_execution_time', getMaxExeTime());

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
ini_set('implicit_flush', true);

ob_implicit_flush(true);

while (ob_get_level() > 0) 
{
  $level = ob_get_level();
  ob_end_clean();
  if (ob_get_level() == $level) break;
}

if (function_exists('apache_setenv')) 
{
  apache_setenv('no-gzip', '1');
  apache_setenv('dont-vary', '1');
}

/* This section runs a ping and echos out the terminal window */
$descriptorspec = 
[
  0 => ['pipe', 'r'],
  1 => ['pipe', 'w'],
  2 => ['pipe', 'w']
];

// Input checking for the post data and interaction with a MySQL database is done here

$tool_command = 'ping 8.8.8.8 -n 10';

$process = proc_open($tool_command, $descriptorspec, $pipes);
stream_set_blocking($pipes[1], false);
stream_set_blocking($pipes[2], false);
$proc_details = proc_get_status($process);

while ($s = fgets($pipes[1])) 
{
  echo $s;
  flush();
  sleep(0.3);
}

If at any time during this while loop the user attempts to reload the page, they will just get the tab loading icon. If I attempt to run another PHP script from jQuery, it'll just queue until the while loop is done. What is causing the problem here? PHP, Ajax, the apache server, HTTP requests, something else?


Aucun commentaire:

Enregistrer un commentaire