0

We are switching servers on a project that makes 18 soap connections in a row from the client to the server. On the old server, we had no problem with this, but on the new server, always one specific call causes the Error Fetching http headers error, and occasionally another call will fail the same way. All other calls work just fine.

All calls follow the exact same principle:

  1. Data is collected and stored in an array (this is the only difference in these calls - what data is submitted).
  2. Array is encoded as json.
  3. json String is added to ZIP file.
  4. Content of ZIP file is encrypted using openssl.
  5. Encrypted string is base64 encoded.
  6. The encoded string is sent to the server.

And out of the 18 calls, only the same one fails - number 17 - and it fails every time. On occasion, another one will fail.

The data for every one of these calls is mostly identical during this test - one parameter in the array is different, and two other keys are added to the array for the call that fails.

I have looked into StayAlive (disabling it on the client causes a second call to fail as well), I have looked into cutting the connection (as mentioned here: SoapFault exception: [HTTP] Error Fetching http headers ), I have tried changing timeout, but the response generally comes within less than half a second for every call including the failing one.

Here's the client code:

$client = new SoapClient(
    null, array(
        'location'  => $location,
        'uri'       => $urn,
        'trace'     => 1
    )
);

try
{
    // generate new object
    $auth=new authentication_header($system['Username'], $system['Password']);

    // create authentication header values
    $authvalues=new SoapVar($auth, SOAP_ENC_OBJECT, 'authenticate');

    // generate header
    $header=new SoapHeader("domain.com", "authenticate", $authvalues, false, "http://schemas.xmlsoap.org/soap/actor/next");


    /* *****************************
    *         SEND DATA            *
    ***************************** */
    $result = $client-> __soapCall("Process",array($b64String, $key, $system['UserId'], $fileSize, $connectionTest), null, $header);

    //handle response
    [...]
}
catch(SoapFault $e)
{
    $msg = $e->getMessage();
    echo "\n<br>Unknown error: " . $msg . "<br>\n";
    $response = $client->__getLastResponseHeaders();
    echo $response . "<br>\n";
    Datapipe_Error_Log($msg, $response);

    return false;
}
catch(Exception $e)
{
    //write out the error
    echo "Exception:<br>";
    var_dump($e);
    Datapipe_Error_Log('Datapipe Exception', $e);
    return false;
}

Here is the server code:

//disable cache
ini_set("soap.wsdl_cache_enabled", "0");

//set the time limit
set_time_limit(60000);
ini_set('memory_limit', '256M');

//init main server object
$server = new SoapServer(null, array('uri' => "urn://domain.com", 'encoding' => 'UTF-8'));

$server->addFunction('Process');
$server->handle();  

function Process($fileString, $ekey, $districtId, $fileSize, $test=false)
{
    //grab the xml
    $xml = file_get_contents('php://input');

    //write the string to file 
    file_put_contents("debug.txt", "*** " . $test . "***\n" . $xml, FILE_APPEND); 

    // other processing ...
    [...]
}

It looks like for this one call the file_put_contents function is never executed.

I can see the point that maybe there are too many connections open since these calls happen in very rapid succession, and we're using PHP 5.3.5 on the client (the server is on 5.6.1). But I tried implementing the solution described in the link I added here ($this->httpsocket = NULL; in an extension of SoapClient) without any change.

We can't update the PHP version on the client for specific reasons, but the client hasn't changed for this test. Our Linux guy created a new server, and everything works - except this one call fails.

The setting default_socket_timeout is set to 60 (at least when I use php -a from a terminal window), but so far every single call takes less than half a second to respond.

Adding

var_dump($client->__getLastRequest());
var_dump($client->__getLastResponse());

To the code resulted in what appears to be correct XML data as request and NULL as last response.

The server always throws this error when this happens:

[Wed Nov 12 15:23:03.080700 2014] [core:notice] [pid 9731] AH00052: child pid 10276 exit signal Segmentation fault (11)

As far as I know, there are no 3rd party extensions running other than Zend. Here's the php -v output:

PHP 5.6.1 (cli)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies

And here's php -m :

[PHP Modules]
Core
ctype
date
dom
ereg
filter
hash
iconv
json
libxml
mhash
mysql
mysqli
mysqlnd
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Reflection
session
SimpleXML
soap
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zip
zlib

[Zend Modules]

I have over 5GB of free RAM (free -m), so I don't think that's it, either (some posts mention memory issues caused by loops - but then, the code fails way before anything big is executed...).

Here's some relevant entries in the error log when Apache reboots that might help:

[Wed Nov 12 13:57:59.063896 2014] [mpm_prefork:notice] [pid 9677] AH00163: Apache/2.4.10 (Linux/SUSE) OpenSSL/1.0.1i-fips PHP/5.6.1 configured -- resuming normal operations
[Wed Nov 12 13:57:59.063980 2014] [core:notice] [pid 9677] AH00094: Command line: '/usr/sbin/httpd2-prefork -f /etc/apache2/httpd.conf -D SSL -D SYSTEMD -D FOREGROUND'

This is about as far as I can troubleshoot this until your Linux guy comes back in two days, and unfortunately, gdb doesn't seem to be installed, and I don't want to mess with the server too much without the admin's OK...

At this point, I have to assume it's a corrupted PHP or Apache installation or a version conflict or something.

--- Update ---

I ran the test again and disabled two of the calls to see if the issue persists even if the call in question is no longer the 17th entry of the loop. It does - it's still the same call that fails. So the failure does not seem to be related to how many calls are made before. It seems to always affect the call with a specific parameter in the array.

But by now, I have changed all the submitted data for this call and even added 1kB of spaces to see if that would make a difference - still the same issue. I can't think of anything else I can change that would explain this.

--- End Update ---

Any further ideas I can try?

Community
  • 1
  • 1
semmelbroesel
  • 543
  • 1
  • 8
  • 27

1 Answers1

1

try 'keep_alive' => false

$client = new SoapClient($wsdl,array(
'trace' => true,
'cache_wsdl' => WSDL_CACHE_BOTH,
'keep_alive' => false
));
Khanh Van
  • 1,422
  • 11
  • 6