phpcurl

php cURL curl_exec returns false, stopping execution before initializing with errno 43 BAD_FUNCTION_ARGUMENT


I send several curl requests from service A (running phpunit tests) to service B (api).

After a fixed amount of curl calls, the curl_exec function returns false with code 43 which means BAD_FUNCTION_ARGUMENT.

The error always occurs at the same test in my set of tests. If I remove a test before the error hits, the error simply shifts forward to the next test that uses curl.

This looks like I am hitting a (hard) limit somethere, this is what I know:

None of these help me prevent the curl error, lets take a look at the verbose info of the request before the error and the info of the error.

The last successful curl before the error

* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
> GET /user/2645f3b7-a187-47c0-95d3-0ab1696501eb/ HTTP/1.1
Host: localhost
Accept: */*
Accept-Encoding: deflate, gzip, br, zstd
Connection: close
Authorization: Bearer: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXlzIjp7lciJ9.JivFp5Rp6YcQ5KkcEp_7WiVB2SmIRdnXcsg86r3eGIE

* Request completely sent off
< HTTP/1.1 200 OK
< Date: Wed, 08 May 2024 12:28:43 GMT
< Server: Apache/2.4.54 (Unix) OpenSSL/1.0.2u PHP/8.2.0 mod_wsgi/3.5 Python/2.7.18 mod_fastcgi/mod_fastcgi-SNAP-0910052141 mod_perl/2.0.11 Perl/v5.30.1
< X-Powered-By: PHP/8.2.0
< Set-Cookie: _ssid=0qupDtygjuhsOEQyDYilnLSfcEymOUDKDwdTVXEyQqC68D3b8tkPH6-SCby2qcKB%2CsJU1%2C4vbk39hLbeT%2CWGgdh%2Ctn9C4SOerZ2YHh6VWIrsI3Br8X-Jyu1XCfsMk8Lu; expires=Wed, 15 May 2024 12:28:43 GMT; Max-Age=604800; path=/; HttpOnly; SameSite=Strict
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< Access-Control-Allow-Origin: *
< Content-Length: 1208
< Connection: close
< Content-Type: application/json
< 
* Closing connection

With the following curlinfo

array(40) {
  ["url"]=>
  string(57) "http://localhost/user/2645f3b7-a187-47c0-95d3-0ab1696501eb/"
  ["content_type"]=>
  string(16) "application/json"
  ["http_code"]=>
  int(200)
  ["header_size"]=>
  int(703)
  ["request_size"]=>
  int(0)
  ["filetime"]=>
  int(-1)
  ["ssl_verify_result"]=>
  int(0)
  ["redirect_count"]=>
  int(0)
  ["total_time"]=>
  float(1.024873)
  ["namelookup_time"]=>
  float(5.2E-5)
  ["connect_time"]=>
  float(0.000393)
  ["pretransfer_time"]=>
  float(0.000602)
  ["size_upload"]=>
  float(44)
  ["size_download"]=>
  float(114)
  ["speed_download"]=>
  float(111)
  ["speed_upload"]=>
  float(42)
  ["download_content_length"]=>
  float(114)
  ["upload_content_length"]=>
  float(44)
  ["starttransfer_time"]=>
  float(1.024833)
  ["redirect_time"]=>
  float(0)
  ["redirect_url"]=>
  string(0) ""
  ["primary_ip"]=>
  string(3) "::1"
  ["certinfo"]=>
  array(0) {
  }
  ["primary_port"]=>
  int(80)
  ["local_ip"]=>
  string(3) "::1"
  ["local_port"]=>
  int(59910)
  ["http_version"]=>
  int(2)
  ["protocol"]=>
  int(1)
  ["ssl_verifyresult"]=>
  int(0)
  ["scheme"]=>
  string(4) "HTTP"
  ["appconnect_time_us"]=>
  int(0)
  ["connect_time_us"]=>
  int(393)
  ["namelookup_time_us"]=>
  int(52)
  ["pretransfer_time_us"]=>
  int(602)
  ["redirect_time_us"]=>
  int(0)
  ["starttransfer_time_us"]=>
  int(1024833)
  ["total_time_us"]=>
  int(1024873)
  ["effective_method"]=>
  string(4) "POST"
  ["capath"]=>
  string(0) ""
  ["cainfo"]=>
  string(0) ""
}

Then the error hits, no verbose information only curlinfo with no values

array(40) {
  ["url"]=>
  string(57) "http://localhost/role/ROLE-RKX0TRLT1QGF/"
  ["content_type"]=>
  NULL
  ["http_code"]=>
  int(0)
  ["header_size"]=>
  int(0)
  ["request_size"]=>
  int(0)
  ["filetime"]=>
  int(-1)
  ["ssl_verify_result"]=>
  int(0)
  ["redirect_count"]=>
  int(0)
  ["total_time"]=>
  float(0)
  ["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(-1)
  ["starttransfer_time"]=>
  float(0)
  ["redirect_time"]=>
  float(0)
  ["redirect_url"]=>
  string(0) ""
  ["primary_ip"]=>
  string(0) ""
  ["certinfo"]=>
  array(0) {
  }
  ["primary_port"]=>
  int(0)
  ["local_ip"]=>
  string(0) ""
  ["local_port"]=>
  int(0)
  ["http_version"]=>
  int(0)
  ["protocol"]=>
  int(0)
  ["ssl_verifyresult"]=>
  int(0)
  ["scheme"]=>
  string(0) ""
  ["appconnect_time_us"]=>
  int(0)
  ["connect_time_us"]=>
  int(0)
  ["namelookup_time_us"]=>
  int(0)
  ["pretransfer_time_us"]=>
  int(0)
  ["redirect_time_us"]=>
  int(0)
  ["starttransfer_time_us"]=>
  int(0)
  ["total_time_us"]=>
  int(0)
  ["effective_method"]=>
  string(3) "GET"
  ["capath"]=>
  string(0) ""
  ["cainfo"]=>
  string(0) ""
}

Clearly curl is not even initialized and it crashes. The errno is set to 43 BAD_FUNCTION_ARGUMENT but there is no way of figuring out what causes this. If I run only a subset of tests including the one that errors when running all tests, all works fine.

In case anyone has suggestions on how to figure out what is causing this, maybe some curl option I haven't heard of. Maybe the max connection count on the apache server which I assume are closed because of the CURLOPT_FORBID_REUSE option and 'Connection: close' header.


Solution

  • The error was created by curl version used at the time which was 8.1.2. If you are experiencing unexpected 43 BAD_FUNCTION_ARGUMENT errors please update your curl. At the time of writing curl 8.7.1 does not produce this error.