dunglas / frankenphp

🧟 The modern PHP app server
https://frankenphp.dev
MIT License
6.89k stars 236 forks source link

Uncaught Error: Call to undefined function dirname() #685

Closed CvekCoding closed 5 months ago

CvekCoding commented 7 months ago

What happened?

My Symfony6 application can not start with the following error:

{"level":"error","ts":1711266796.1390681,"msg":"PHP Fatal error:  Uncaught Error: Call to undefined function dirname() in /app/public/index.php:5\nStack trace:\n#0 {main}\n  thrown in /app/public/index.php on line 5","syslog_level":"err"}

My Dockerfile relevant part where I build frankenphp:

#syntax=docker/dockerfile:1.4

# Custom Frankenphp build
FROM dunglas/frankenphp:latest-builder AS builder

# Copy xcaddy in the builder image
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy

# CGO must be enabled to build FrankenPHP
ENV CGO_ENABLED=1 XCADDY_SETCAP=1
ENV XCADDY_GO_BUILD_FLAGS="-ldflags \"-w -s -extldflags '-Wl,-z,stack-size=0x80000'\""

RUN xcaddy build \
    --output /usr/local/bin/frankenphp \
    --with github.com/dunglas/frankenphp=./ \
    --with github.com/dunglas/frankenphp/caddy=./caddy/ \
    # Mercure and Vulcain are included in the official build, but feel free to remove them
    --with github.com/dunglas/caddy-cbrotli \
    --with github.com/dunglas/mercure/caddy \
    # Add extra Caddy modules here
    --with github.com/mholt/caddy-ratelimit

FROM dunglas/frankenphp:1 AS frankenphp_upstream

# Replace the official binary by the one contained your custom modules
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp

My index.php file is standard:

<?php

use App\Kernel;

require_once dirname(__DIR__).'/vendor/autoload_runtime.php';

return function (array $context) {
    return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

Probably it's important: Im wrapping frankenphp with supervisor:

[program:caddy]
command=frankenphp run --config /etc/caddy/Caddyfile
numprocs=1
autostart=true
autorestart=true
startsecs=0
redirect_stderr=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

So my container starts with Supervisor, which in turn runs Frankenphp and several other console listeners.

Build Type

Docker (Debian Bookworm)

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

# php -i
phpinfo()
PHP Version => 8.3.4

System => Linux b39bc0d0a121 5.4.0-26-generic #30-Ubuntu SMP Mon Apr 20 16:58:30 UTC 2020 x86_64
Build Date => Mar 16 2024 00:12:43
Build System => Linux - Docker
Build Provider => https://github.com/docker-library/php
Configure Command =>  './configure'  '--build=x86_64-linux-gnu' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--with-mhash' '--with-pic' '--enable-mbstring' '--enable-mysqlnd' '--with-password-argon2' '--with-sodium=shared' '--with-pdo-sqlite=/usr' '--with-sqlite3=/usr' '--with-curl' '--with-iconv' '--with-openssl' '--with-readline' '--with-zlib' '--enable-phpdbg' '--enable-phpdbg-readline' '--with-pear' '--with-libdir=lib/x86_64-linux-gnu' '--enable-embed' '--enable-zts' '--disable-zend-signals' 'build_alias=x86_64-linux-gnu'
Server API => Command Line Interface
Virtual Directory Support => enabled
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => /usr/local/etc/php/php.ini
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
Additional .ini files parsed => /usr/local/etc/php/conf.d/app.ini,
/usr/local/etc/php/conf.d/app.prod.ini,
/usr/local/etc/php/conf.d/docker-php-ext-amqp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-apcu.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bcmath.ini,
/usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_pgsql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini

PHP API => 20230831
PHP Extension => 20230831
Zend Extension => 420230831
Zend Extension Build => API420230831,TS
PHP Extension Build => API20230831,TS
Debug Build => no
Thread Safety => enabled
Thread API => POSIX Threads
Zend Signal Handling => disabled
Zend Memory Manager => enabled
Zend Multibyte Support => provided by mbstring
Zend Max Execution Timers => enabled
IPv6 Support => enabled
DTrace Support => disabled

Registered PHP Streams => https, ftps, compress.zlib, php, file, glob, data, http, ftp, phar, zip
Registered Stream Socket Transports => tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2, tlsv1.3
Registered Stream Filters => zlib.*, convert.iconv.*, string.rot13, string.toupper, string.tolower, convert.*, consumed, dechunk

This program makes use of the Zend Scripting Language Engine:
Zend Engine v4.3.4, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.4, Copyright (c), by Zend Technologies

Relevant log output

No response

CvekCoding commented 7 months ago

At the same time, a simple restart of the container sometimes helps and Frankenphp begins to process requests successfully

dunglas commented 7 months ago

This looks a lot like an opcache corruption issue: https://github.com/dunglas/symfony-docker/issues/578

Do you use any custom opcache option?

CvekCoding commented 7 months ago

My opcache related configs.

#api/docker/frankenphp/conf.d/app.prod.ini

opcache.preload_user = root
opcache.preload = /app/config/preload.php
#api/config/preload.php

<?php

if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
    require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
}
#api/docker/php/conf.d/api-platform.prod.ini

apc.enable_cli = 1
date.timezone = UTC
session.auto_start = Off
short_open_tag = Off

# https://symfony.com/doc/current/performance.html

opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.memory_consumption = 256
opcache.validate_timestamps = 0
realpath_cache_size = 4096K
realpath_cache_ttl = 600
CvekCoding commented 7 months ago

BTW the file /var/cache/prod/App_KernelProdContainer.preload.php doesnt exist

CvekCoding commented 7 months ago

Sorry, it does - this file exists in cache directory

withinboredom commented 7 months ago

If I'm understanding correctly, if dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php' doesn't exist when the container starts, you'll run into this bug. Since it is in the cache, I suspect that is what is going on?

CvekCoding commented 7 months ago

I think no. It's the same container and sometimes it runs to the issue, sometimes - not.

withinboredom commented 7 months ago

If you disable preloading, does the issue still occur?

CvekCoding commented 7 months ago

You are right. When I disabled this script, the issue gone

fogrye commented 5 months ago

in file #api/docker/frankenphp/conf.d/app.prod.ini opcache.preload should be the same as path to file #api/config/preload.php