3

I've been researching and experimenting with this problem for a while now, and have yet to find a workable solution, so I think it's time to call for help.

I've got a problem with curl_exec, but only on a specific server. Here's some background, first:

  • CPU: Intel Core I7
  • RAM: 64GB
  • OS: Windows 8.0
  • Server: Apache 2.4.4 x86 TS
  • PHP version: 5.5.1 x86 TS w/xDebug 2.2.3
  • cURL version: 7.30.0

PHP code that exhibits the problem:

$input_vars = (!empty($_POST)) ? filter_input_array(INPUT_POST) : array();
$url = 'http://192.168.1.100/geekcavecreations/Morti/chatbot/conversation_start.php';
$qs = '?';
foreach ($input_vars as $key => $value)
{
  $qs .= "$key=$value&";
}
$qs= rtrim($qs, '&');
$url .= $qs;
$bot_id = $input_vars['bot_id'];
$options = array(
    CURLOPT_USERAGENT => 'Program O XML API',
    CURLOPT_RETURNTRANSFER => true,
    //CURLOPT_POST => 1,
    CURLOPT_MAXREDIRS => 5,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 5,
);
$ch = curl_init($url);
curl_setopt_array($ch, $options);
//curl_setopt($ch, CURLOPT_POSTFIELDS, $input_vars);
$data = curl_exec($ch);
$debug = curl_getinfo($ch);
curl_close($ch);
echo '<pre>Data = ', htmlentities($data), '</pre><br>';
var_dump($debug);

As can be seen, I've tried this with both GET and POST, and both give the same results. The timeout options listed above are there so that the script won't run indefinately. I've had it hang for over 3 hours before I would stop the Apache service to stop the hangup (just canceling in the browser won't do it). The output from the script is as follows:

array (size=26)
  'url' => string 'ht tp://192.168.1.100/geekcavecreations/Morti/chatbot/conversation_start.php?say=hello&bot_id=1&convo_id=78a9s39gut34lurq055in5s6r4&format=xml' (length=141)
  'content_type' => null
  'http_code' => int 0
  'header_size' => int 0
  'request_size' => int 203
  'filetime' => int -1
  'ssl_verify_result' => int 0
  'redirect_count' => int 0
  'total_time' => float 5
  'namelookup_time' => float 0
  'connect_time' => float 0
  'pretransfer_time' => float 0
  'size_upload' => float 0
  'size_download' => float 0
  'speed_download' => float 0
  'speed_upload' => float 0
  'download_content_length' => float -1
  'upload_content_length' => float 0
  'starttransfer_time' => float 0
  'redirect_time' => float 0
  'redirect_url' => string '' (length=0)
  'primary_ip' => string '192.168.1.100' (length=13)
  'certinfo' => 
    array (size=0)
      empty
  'primary_port' => int 80
  'local_ip' => string '192.168.1.100' (length=13)
  'local_port' => int 2546

Data = 

(couldn't figure out a better way of formatting that, sorry)

Also on this same computer are several Virtual Machines, each with different OS/Server/PHP versions, and all with exactly the same physical document root, which is located on the host machine. These machines range from Windows 7/IIS to CentOS/Apache 2.2, and other combinations, and all of them, without exception, run this same script without trouble, and output the expected XML document. If I run the URL in just a web browser, the output is as follows:

<?xml version="1.0"?>
<program_o>
  <version>2.3.0</version>
  <status><success>1</success></status>
  <bot_id>1</bot_id>
  <bot_name>Morti</bot_name>
  <user_id>1</user_id>
  <user_name>Seeker</user_name>
  <chat>
    <line>
      <input>hello</input>
      <response>And a good failed to you, undefined. How are you?</response>
    </line>
  </chat>
</program_o>

I've also taken the above XML output and saved it to a file, and had the problem script perform the cURL call on the URL for that saved XML file, and the script works without a problem at that point, so I also created a mock-up script that only creates a SimpleXMLElement object, populates a few new tags, and then echo's the asXML() output from the created object (essentially what conversation_start.php does, but far less complex), and I get the same problem. The code for the mock-up script is below:

$xml = new SimpleXMLElement('<program_o></program_o>');
$xml->addChild('version', '2.3.0');
$status = $xml->addChild('status');
$status->addChild('success', '1');
$xml->addChild('bot_id', '1');
$xml->addChild('bot_name', 'Morti');
$xml->addChild('user_id', '1');
$xml->addChild('user_name', 'Seeker');
$chat = $xml->addChild('chat');
$line = $chat->addChild('line');
$line->addChild('input', 'hello');
$line->addChild('response', 'And a good failed to you, undefined. How are you?');
$output = $xml->asXML();
header('Content-type: text/xml');
exit($output);

I'm pretty much at my wits end here. I've changed PHP versions, Apache versions, tried countless suggestions that I've found here on SO to other issues with cURL freezing, as found here, here and here, among a double dozen or more others.

And now that I've written a book to present my problem, I have to ask: How can I get cURL to keep from hanging on a Windows 8 platform?

4

1 回答 1

1

好吧,我似乎终于找到了问题的根源。似乎当您对与执行调用的脚本相同的服务器执行 cURL 调用时,如果“调用者”和“被调用者”脚本都试图使用相同的会话 ID,则会发生死锁,导致两者脚本等到另一个释放会话。我最终添加了一个测试以查看是否已经有一个会话 id 正在使用,如果是,则调用脚本不会启动会话。如果没有会话ID,则调用者启动会话,获取会话ID,然后销毁会话,这允许“被调用者”脚本不受限制地访问所述会话,从而消除死锁情况。下面是我用来执行此操作的代码:

$convo_id = (isset ($request_vars['convo_id'])) ? $request_vars['convo_id'] : get_convo_id();
// do stuff here
function get_convo_id()
{
  session_name('Program O XML GUI');
  session_start();
  $convo_id = session_id();
  session_destroy();
  return $convo_id;
}

使用这种方法,一切都按预期工作。我真诚地希望这在未来对其他人有用。

于 2013-07-23T14:00:20.270 回答