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

PHP Fatal error: Maximum call stack size of 83360 bytes reached during compilation. Try splitting expression #380

Closed
cdaguerre opened this issue Dec 13, 2023 · 19 comments
Labels
documentation Improvements or additions to documentation

Comments

@cdaguerre
Copy link

cdaguerre commented Dec 13, 2023

Hi, I tried FrankenPHP on 2 different Symfony 6.3 projects and get the error:

Maximum call stack size of 83360 bytes reached during compilation. Try splitting expression in /app/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php on line 351

The symfony/framework-bundle version is 6.3.4.
Using PHP 8.3 alpine version.

I'm not sure what compilation refers to in this context and Google didn't help ;)

@cdaguerre
Copy link
Author

I'm also seeing the following line on startup:

2023-12-13 15:39:24 2023/12/13 14:39:24.413     INFO    using provided configuration    {"config_file": "/etc/caddy/Caddyfile", "config_adapter": "caddyfile"}
2023-12-13 15:39:24 2023/12/13 14:39:24.414     WARN    Import file is empty    {"file": "/etc/caddy/conf.d/logging/dev.caddy"}
2023-12-13 15:39:24 2023/12/13 14:39:24.418     WARN    admin   admin endpoint disabled
2023-12-13 15:39:24 2023/12/13 14:39:24.442     INFO    FrankenPHP started 🐘    {"php_version": "8.3.0"}
2023-12-13 15:39:24 2023/12/13 14:39:24.463     INFO    autosaved config (load with --resume flag)      {"file": "/config/caddy/autosave.json"}
2023-12-13 15:39:24 2023/12/13 14:39:24.464     INFO    serving initial configuration
2023-12-13 15:39:24 2023/12/13 14:39:24.471     WARN    PHP Warning:  Failed to set memory limit to 0 bytes (Current memory usage is 2097152 bytes) in Unknown on line 0

@withinboredom
Copy link
Collaborator

Might be related to #378?

@cdaguerre
Copy link
Author

Well it's the same error but I'm not compiling for a standalone binary.
I'm trying it out in our local development setup (docker-compose), where we favor developer experience and have no production optimizations.
For instance, we have memory_limit set to -1 there.
Any idea how I can allow a higher limit for this setting ? I've never seen it before and can't find anything online. Is this even a PHP error?

@withinboredom
Copy link
Collaborator

I meant specifically:

Have you warmed the cache

I do know there is something to be done here; I use Symfony at work and write compiler passes from time to time, but I'm not usually doing devops on it, so I don't know how to perform a compile pass on the container. (maybe composer dump?)

Sadly, this seems to be a Symfony-specific thing and I won't be much help here. Maybe @dunglas has some insight?

For instance, we have memory_limit set to -1 there.

Hmmm, usually, I see the other way around; lower limits in dev than in prod (since you don't want to end up having everything working in dev, but crashing in prod due to hitting limits).

@konrado
Copy link

konrado commented Dec 13, 2023

I have seen this issue a few times, but manually removing the cache directory fixes it. IMO it seems to be related to cache warming. So you can easily "fix" it locally, but it's annoying.

@cdaguerre
Copy link
Author

Actually probably more related to php/php-src#12234 and #223...
I'm not to sure what should be done here... Maybe this should indeed be improved at symfony/framework-bundle level.
Any thoughts @dunglas ?

@dunglas
Copy link
Owner

dunglas commented Dec 13, 2023

Unfortunately it's a tradeoff.

There are 3 options:

  1. Using Debian variants in dev (it's what I recommend to do)
  2. Creating a custom Alpine build with an increased stack size for dev (in prod, it's better to keep with the defaults)
  3. Increasing the default size in our image, but it will affect "negatively" all apps in production for some that need this only in dev

It's unlikely that the "problem" is in Symfony itself (and it's not really a problem actually, there are just many files to "compile" and it's too much for the default stack limit). It's more likely in the bundles used or the custom code the app. It can probably be optimized in your app itself... but does it worth it as it's unlikely that this affect the production environment (where the cache is already populated)?

@dunglas dunglas added the documentation Improvements or additions to documentation label Dec 14, 2023
@darkweak
Copy link

darkweak commented Dec 14, 2023

Actually with a simple API Platform it doesn't work using the dunglas/frankenphp:latest-builder-alpine combined to dunglas/frankenphp:latest-alpine so we can't build any FrankenPHP instances with additional modules.

It can probably be optimized in your app itself

That doesn't seem to be an application issue (or maybe API Platform itself should be optimized too).

Using Debian variants in dev (it's what I recommend to do)

That means, we have to rewrite the Dockerfile to use the Debian distribution instead of the default one to use apt instead of apk.

@cdaguerre
Copy link
Author

cdaguerre commented Dec 14, 2023

It seems it always occurs at the exact same point during symfony container compilation, notably here: https://github.com/symfony/framework-bundle/blob/4a4e93d93f2081c8e90a289644198fc2ec6258e0/DependencyInjection/Configuration.php#L337
I tried 2 pretty different applications and it was the same on the issue raised by @dunglas here: php/php-src#12234
Did it fail at the same line for you @darkweak ?

That's why I was wondering if it can not be optimized at symfony/framework-bundle level.
My guess is that even the symfony demo doesn't work out of the box with cold cache.

For the record, I increased the stack size manually like here and other problems started popping up (redis connection timeouts !?) on stuff that works without fiddling the stack size...

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

@darkweak can you post your Dockerfile? Are you sure that you're increasing the stack size as we do in the official images in your custom build including extra modules? I'm not able to reproduce the problem with our official Alpine images (no custom build) and API Platform.

@cdaguerre Did you try to increase the stack size? It can be done by changing the value here: https://github.com/dunglas/frankenphp/blob/main/alpine.Dockerfile#L88 (the stack-size flag)?

@cdaguerre
Copy link
Author

arg sorry @dunglas I updated my comment above ;)

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

@cdaguerre are you using the worker mode? Redis timeouts are likely unrelated.

@cdaguerre
Copy link
Author

I tried both, both the same.

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

And do you have the same issue with the Debian image?

@darkweak
Copy link

@dunglas I'm following the FrankenPHP documentation

FROM dunglas/frankenphp:latest-builder-alpine AS builder
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy

COPY ./middleware ./middleware

ENV CGO_ENABLED=1 XCADDY_SETCAP=1
RUN xcaddy build \
    --output /usr/local/bin/frankenphp \
    --with github.com/dunglas/frankenphp=./ \
    --with github.com/dunglas/frankenphp/caddy=./caddy/ \
    --with github.com/dunglas/mercure/caddy \
    --with github.com/dunglas/vulcain/caddy \
    --with connector=./middleware

# Versions
# hadolint ignore=DL3007
FROM dunglas/frankenphp:latest-alpine AS frankenphp_upstream
FROM composer/composer:2-bin AS composer_upstream


# The different stages of this Dockerfile are meant to be built into separate images
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
# https://docs.docker.com/compose/compose-file/#target


# Base FrankenPHP image
FROM frankenphp_upstream AS frankenphp_base
COPY --from=builder --link /usr/local/bin/frankenphp /usr/local/bin/frankenphp

WORKDIR /app

# persistent / runtime deps
# hadolint ignore=DL3018
RUN apk add --no-cache \
		acl \
		file \
		gettext \
		git \
	;

RUN set -eux; \
    install-php-extensions \
		apcu \
		intl \
		opcache \
		gd \
		zip \
    ;

###> recipes ###
###> doctrine/doctrine-bundle ###
RUN set -eux; \
    install-php-extensions pdo_pgsql
###< doctrine/doctrine-bundle ###
###< recipes ###

COPY --link api/frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/
COPY --link --chmod=755 api/frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
COPY --link api/frankenphp/Caddyfile /etc/caddy/Caddyfile

ENTRYPOINT ["docker-entrypoint"]

# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV PATH="${PATH}:/root/.composer/vendor/bin"

COPY --from=composer_upstream --link /composer /usr/bin/composer

HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ]

# Dev FrankenPHP image
FROM frankenphp_base AS frankenphp_dev

ENV APP_ENV=dev XDEBUG_MODE=off
VOLUME /app/var/

RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

RUN set -eux; \
	install-php-extensions \
    	xdebug \
    ;

COPY --link api/frankenphp/conf.d/app.dev.ini $PHP_INI_DIR/conf.d/

CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ]

# Prod FrankenPHP image
FROM frankenphp_base AS frankenphp_prod

ENV APP_ENV=prod
ENV FRANKENPHP_CONFIG="import worker.Caddyfile"

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

COPY --link api/frankenphp/conf.d/app.prod.ini $PHP_INI_DIR/conf.d/
COPY --link api/frankenphp/worker.Caddyfile /etc/caddy/worker.Caddyfile

# prevent the reinstallation of vendors at every changes in the source code
COPY --link api/composer.* api/symfony.* ./
RUN set -eux; \
	composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress

# copy sources
COPY --link ./api ./
RUN rm -Rf frankenphp/

RUN set -eux; \
	mkdir -p var/cache var/log; \
	composer dump-autoload --classmap-authoritative --no-dev; \
	composer dump-env prod; \
	composer run-script --no-dev post-install-cmd; \
	chmod +x bin/console; sync;

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

@darkweak the documentation assumes that you're using the GNU libc and not musl: FROM dunglas/frankenphp:latest-builder AS builder ;)

I added a note about musl in #385. That should fix your issue.

@darkweak
Copy link

But if you provide a latest-builder-alpine image, I assume that you support alpine 😂
Thank you for the documentation update.

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

We do support Alpine ;) This option is only necessary for people using Alpine + a custom build + Symfony in dev mode. Quite an edge case.

@dunglas
Copy link
Owner

dunglas commented Dec 14, 2023

That bein said, and even if it's not related to this issue. I'm considering switching from Alpine to Debian in API Platform and Symfony Docker, to prevent this kind of weird edge cases. PHP has many known issues with Alpine.

@dunglas dunglas closed this as completed Feb 26, 2024
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

5 participants