eloquence icon indicating copy to clipboard operation
eloquence copied to clipboard

Infinite Loop on callHook and whereIn functions causing apache to restart due to stack overflow

Open charlesaugust44 opened this issue 4 years ago • 6 comments
trafficstars

I'm developing a new API on Lumen and renaming the columns of the legacy database.

I have two tables, Images and Variants, Images has many Variants.

  • Variants is the mapped name of the table usu_t075varest
  • Images is the mapped name of the table usu_t075desest

Mapped this relation as the Lumen docs suggest:

Image.php

public function variants() {
        return $this->hasMany(Variant::class, 'usu_coddes','usu_coddes');
}
  • usu_coddes is the foreign key on Variants table.
  • usu_coddes is the primary key on Images table.

Calling the the route \api\images\SR16105G13 with no authentication:

public function read($id) {
   $image = Image::where('usu_coddes', $id)
                  ->with('variants')
                  ->first();

   if ($image === null)
      return response(null, 404);

   return response()->json($image);
}

The PHP interpreter never goes beyond the with('variants') function, i did some step by step debugging with Zend debugger and saw that in the function callHook on Sofa\Hookable\Builder it calls the callParent function with the first argument "whereIn" so it will call the parent whereIn on Eloquent\Builder but that function doesn't exists there, so PHP reverts the call back to whereIn on Sofa\Hookable\Builder that calls callHook and so on, until call stack is exceeded for Apache and it reboots killing the connection.

I'm not very familiar with Lumen Eloquent structure to make any modification to solve this, anyone could give me a hand or commit the solution?

charlesaugust44 avatar Mar 31 '21 19:03 charlesaugust44

I discovered that the function whereIn that callParent is trying to call is on Illuminate\Database\Query\Builder that is extended on Sofa\Eloquence\Query\Builder.

charlesaugust44 avatar Mar 31 '21 19:03 charlesaugust44

For some reason, this works on php7.3-fpm (with nginx) but goes into this infinite loop in php8.0-fpm and kills fpm (it restarts) and results in the same apache behavior above (nginx shows "502 Bad Gateway")

More details

  • https://laracasts.com/discuss/channels/servers/php-8-fpm-sigsegv-signal-11
  • https://stackoverflow.com/questions/67423576/laravel-php-8-fpm-sigsegv-signal-11

chrisgo avatar May 06 '21 18:05 chrisgo

We're also seeing this infinite loop leading to a segfault. In our case it's when using orderBy on a model that's using Eloquence. Same issue with callParent it seems.

https://gist.github.com/bericp1/b5b0c77a55bed87eacb2109156c48558

~We also are only seeing this issue on PHP 7.4 and PHP 8.0.~ (See edit below)

Our composer.json entry:

        "sofa/eloquence": "dev-master",

And composer.lock:

        {
            "name": "sofa/eloquence",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/jarektkaczyk/eloquence.git",
                "reference": "7863ed50e0a8463efd2058ffa51c1f4908860969"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/jarektkaczyk/eloquence/zipball/7863ed50e0a8463efd2058ffa51c1f4908860969",
                "reference": "7863ed50e0a8463efd2058ffa51c1f4908860969",
                "shasum": ""
            },
            "require": {
                "php": ">=7.1.0",
                "sofa/eloquence-base": ">=5.5",
                "sofa/eloquence-mappable": ">=5.5",
                "sofa/eloquence-metable": ">=5.5",
                "sofa/eloquence-mutable": ">=5.5",
                "sofa/eloquence-validable": ">=5.5"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.0",
                "mockery/mockery": "^1.0",
                "phpunit/phpunit": "^9.5",
                "squizlabs/php_codesniffer": "2.3.3"
            },
            "default-branch": true,
            "type": "library",
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jarek Tkaczyk",
                    "email": "[email protected]",
                    "homepage": "http://softonsofa.com/",
                    "role": "Developer"
                }
            ],
            "description": "Flexible Searchable, Mappable, Metable, Validation and more extensions for Laravel Eloquent ORM.",
            "keywords": [
                "eloquent",
                "laravel",
                "mappable",
                "metable",
                "mutable",
                "searchable"
            ],
            "support": {
                "issues": "https://github.com/jarektkaczyk/eloquence/issues",
                "source": "https://github.com/jarektkaczyk/eloquence"
            },
            "funding": [
                {
                    "url": "https://softonsofa.com",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/jarektkaczyk",
                    "type": "github"
                }
            ],
            "time": "2020-12-05T10:37:05+00:00"
        }

Update

Turns out actually that this loop does not happen on PHP 7.4 (our specific version is 7.4.16) and only happens on PHP 8.0+ (we specifically tested PHP 8.0.3 and PHP 8.0.6).

So our interim solution is to use PHP 7.4.16 for the time being until sofa/hookable is updated to support PHP 8.0.

bericp1 avatar May 08 '21 16:05 bericp1

@bericp1 This is confirmed only happening on php 8.0+.

Have 2 vagrant boxes 7.3.11-1~deb10u1 and 8.0.3 pointing to the same code and looking at any PHP 8 breaking changes on call_user_func_array() and cannot figure it out.

@charlesaugust44 research is correct, so it seems like this is a matter of having it call Illuminate\Database\Query\Builder instead of the extended method inside Sofa\Eloquence\Query\Builder ... maybe late static bindings so instead of parent::, it needs to be something else?

chrisgo avatar May 09 '21 18:05 chrisgo

I'm getting the nginx "502 Bad Gateway" while running PHP 8.0.6 too.

maxvaser avatar Jun 04 '21 15:06 maxvaser

Could be related to dependency and PR: https://github.com/jarektkaczyk/hookable/pull/31 Using similar fix solved my php8 issues.

ncolgrove avatar Dec 02 '21 20:12 ncolgrove