Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.34.1] Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? #584

Open
czoIg opened this issue Sep 9, 2024 · 14 comments

Comments

@czoIg
Copy link

czoIg commented Sep 9, 2024

Environment details

  • OS: Debian Bullseye
  • PHP version: 8.3
  • Package name and version: google/gax:v1.34.1 (1.34.0 was working without errors)

Steps to reproduce

  1. Error seems a little random, but occurs always at the same place. I couldn't reproduce it myself, because for many thousands requests, there's like 5-10 errors per day.

Code example

Exception trace

{
    "class": "Error",
    "message": "Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?",
    "code": 0,
    "file": "/app/vendor/google/gax/src/CredentialsWrapper.php:247",
    "trace": [
        "/app/vendor/grpc/grpc/src/lib/UnaryCall.php:43",
        "/app/vendor/grpc/grpc/src/lib/BaseStub.php:295",
        "/app/vendor/grpc/grpc/src/lib/BaseStub.php:545",
        "/app/vendor/google/gax/src/Transport/GrpcTransport.php:228",
        "/app/vendor/google/gax/src/GapicClientTrait.php:641",
        "/app/vendor/google/gax/src/Middleware/CredentialsWrapperMiddleware.php:58",
        "/app/vendor/google/gax/src/Middleware/FixedHeaderMiddleware.php:68",
        "/app/vendor/google/gax/src/Middleware/RetryMiddleware.php:89",
        "/app/vendor/google/gax/src/Middleware/RequestAutoPopulationMiddleware.php:73",
        "/app/vendor/google/gax/src/Middleware/OptionsFilterMiddleware.php:61",
        "/app/vendor/google/gax/src/GapicClientTrait.php:606",
        "/app/vendor/google/cloud-pubsub/src/V1/Gapic/PublisherGapicClient.php:909",
        "/app/vendor/google/cloud-core/src/ExponentialBackoff.php:97",
        "/app/vendor/google/cloud-core/src/GrpcRequestWrapper.php:135",
        "/app/vendor/google/cloud-core/src/GrpcTrait.php:81",
        "/app/vendor/google/cloud-pubsub/src/Connection/Grpc.php:284",
        "/app/vendor/google/cloud-pubsub/src/Topic.php:527",
        "/app/vendor/google/cloud-pubsub/src/Topic.php:482",
        ... (app-specific trace)
    ]
}
@pulzarraider
Copy link
Contributor

pulzarraider commented Sep 11, 2024

We also encountered this problem. PHP 8.3 has new feature and tries to detect the recursion. This feature likely doesn't work correctly with the gRPC PHP extension.

The workaround is to disable stack size checks in the PHP INI settings:
zend.max_allowed_stack_size: -1.

@jhoffland
Copy link

We also encounter this issue, incidentally. The possibility of disabling the stack size check, and avoiding the occurrence of the Error, does not mean the code works properly/efficiently. The comment in CredentialsWrapper::getAuthorizationHeaderCallback, where our infinite recursion errors originate, also suggests awareness about error-prone logic.

@romanstingler
Copy link

Happens thousands of times per day on my side.

@hydrapolic
Copy link

Same issue here, happens with gax 1.34.[01] on php 8.3 with swoole/grpc.

@Jakoffe
Copy link

Jakoffe commented Nov 7, 2024

Still an issue with gax 1.35.0 on php 8.3

@seanBlommaert
Copy link

We worked around this by wrapping the call in

    try {
    }
    catch (\Throwable $exception) {
    }

@erik-treehouse
Copy link

This issue Segmentation Fault in 1.68.0 for PHP 8.3 states: Works with grpc 1.66 and that seems to be the case. So if you have the possibility to (downgrade to) using 1.66.0 it can also be used as a workaround

@Komche
Copy link

Komche commented Dec 4, 2024

We worked around this by wrapping the call in

    try {
    }
    catch (\Throwable $exception) {
    }

Which call

@dinobot71
Copy link

thorn in our side for 3 years now. every single time I do any security patching, I have to worry about this happening again. I tried the stack check disabling; and yes that works. But there is clearly still a problem there. How long until it goes wrong in some other way?

@seanBlommaert
Copy link

seanBlommaert commented Feb 3, 2025

Which call

We have done something like this:

    // Execute API query and return the result.
    try {
      $client = $this->googleQueryFactory->getClient();
      $response = $client->runReport($report_parameters);
    }
    catch (\Throwable $exception) {
    }

It doesn't actually fix the issue, but at least allows loading the rest of the page.

@haizadvnet
Copy link

haizadvnet commented Feb 14, 2025

I ran into the Maximum call stack size exceeded error in getAuthorizationHeaderCallback, which seemed to be caused by recursion. I changed the code to execute the callback function directly instead of returning it as a closure, and it resolved the issue:

Original

return function () use ($audience) {
    // Token fetching and validation logic  
};

Modified

$callback_fn = function () use ($audience) {  
    // Token fetching and validation logic  
};  
 
return $callback_fn();  

This worked for my case and seems to have fixed the issue. I’m considering making a pull request, but I’m not entirely sure if this is the right approach. I haven’t done any performance benchmarking or tested it thoroughly in other scenarios.

Is there a reason the closure is necessary?

@czoIg
Copy link
Author

czoIg commented Feb 14, 2025

$callback_fn = function () use ($audience) {  
    // Token fetching and validation logic  
};  
 
return $callback_fn();  

This looks like you may just run the "Token fetching and validation logic" outside of the callback and return its result without using callback at all.

@haizadvnet
Copy link

This looks like you may just run the "Token fetching and validation logic" outside of the callback and return its result without using callback at all.

You're absolutely right. Previously, I was working on a different project that didn’t require authentication, so it seemed fine at the time.

We've now fixed it by adding a retry mechanism in case of a Throwable error:

$maxRetries = 3;
$attempt = 0;
$delay = 100000; // Initial delay in microseconds (100ms)

while ($attempt < $maxRetries) {
    try {
        $attempt++;
        // Execute the operation that may fail
    } catch (\Throwable $e) {
        if ($attempt >= $maxRetries) {
            throw $e; // Re-throw the exception after max retries
        }

        var_dump('Retrying... Attempt: ' . $attempt);
        usleep($delay); // Wait before retrying
        $delay *= 2; // Exponential backoff
    }
}

This ensures that if an error occurs, the request is retried up to three times with an exponential backoff before failing completely.

@avetiq-dev
Copy link

I found the solution Friends!!!!!!!! (google ads php)

return (new GoogleAdsClientBuilder())
->withOAuth2Credential($oAuth2Credential)
->fromFile(storage_path('google/google_ads_php.ini'))
->withTransport('rest')
->build();

you need add "->withTransport('rest') "

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests