问题
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?
回答1:
Well, I seem to have finally gotten to the root of the problem. It seems that when you execute a cURL call to the same server as the script that is doing the calling, and if both the "caller" and the "callee" scripts are trying to use the same session id, a deadlock occurs, causing both scripts to wait till the other releases the session. I ended up adding a test to see if there's already a session id in use, and if so, the calling script doesn't start a session. If there is no session id, then the caller starts a session, obtains the session id, then destroys the session, which allows the "callee" script unfettered access to said session, thus removing the deadlock situation. Below is the code I used to do this:
$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;
}
Using this method, everything works as expected. I sincerely hope that this proves useful to others in the future.
来源:https://stackoverflow.com/questions/17750515/fixing-curl-exec-hangs-in-windows-8-apache