[go: up one dir, main page]

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

Constants in Enum classes causes php-fpm worker to segfault #8133

Closed
alshenetsky opened this issue Feb 21, 2022 · 16 comments
Closed

Constants in Enum classes causes php-fpm worker to segfault #8133

alshenetsky opened this issue Feb 21, 2022 · 16 comments

Comments

@alshenetsky
Copy link
alshenetsky commented Feb 21, 2022

Description

I have such class:

<?php

namespace App\Domain\TournamentTable;

enum ResultsModifier
{
    case HOME;
    case AWAY;
    case OVERTIME;
    case REGULATION_TIME;
    case OVERALL;
    public const SPECIAL_MODIFIERS = [
        ResultsModifier::AWAY,
        ResultsModifier::HOME,
        ResultsModifier::OVERTIME,
        ResultsModifier::REGULATION_TIME,
    ];
}

When I use this constant in a loop in another class, the php-worker crashes

            foreach (ResultsModifier::SPECIAL_MODIFIERS as $modifier) {
// segfault

Output:

[21-Feb-2022 23:28:26] WARNING: [pool www] child 46 exited on signal 11 (SIGSEGV) after 3.227291 seconds from start

The same code works if I:

  • either turn off opcache (opcache.enable = 0)
  • either remove reference to the constant:
foreach ([ResultsModifier::AWAY, ResultsModifier::HOME, ResultsModifier::OVERTIME, ResultsModifier::REGULATION_TIME] as $modifier) {
// works as expected

So it is probably a bug with opcache.

PHP Version

PHP 8.1.3

Operating System

Alpine 3.13

@cmb69
Copy link
Member
cmb69 commented Feb 22, 2022

I cannot reproduce the segfault (PHP-8.1 on Windows CLI; tried with JIT and without). If I put var_dump($modifiers); in the loop body, I get the expected:

enum(App\Domain\TournamentTable\ResultsModifier::AWAY)
enum(App\Domain\TournamentTable\ResultsModifier::HOME)
enum(App\Domain\TournamentTable\ResultsModifier::OVERTIME)
enum(App\Domain\TournamentTable\ResultsModifier::REGULATION_TIME)

Can you please provide a stack backtrace?

@alshenetsky
Copy link
Author

I would be happy to, and I have the coredump file, but when I compiled php with the --enable-debug flag, my application no longer runs:

Assertion failed: zval_get_type(&(*(z))) < 6 (/usr/src/php/ext/opcache/zend_persist_calc.c: zend_persist_zval_calc: 138)

So I can't, sorry.

@alshenetsky alshenetsky changed the title Contants in Enum classes causes php-fpm worker to segfault Constants in Enum classes causes php-fpm worker to segfault Feb 22, 2022
@cmb69
Copy link
Member
cmb69 commented Feb 23, 2022

I think you still could get a backtrace if you're running under gdb; after the assertion has been triggered, typing bt should provide it. However, I guess the assertion failed due to a prior memory corruption. Are you running with JIT enabled (if in doubt, check PHP info)? If so, what's the value of opcache.jit?

@alshenetsky
Copy link
Author
alshenetsky commented Feb 24, 2022

I failed at it. As far as I understand, gdb attaches to one of the fpm processes. But my php-fpm (when compiled with --enable-debug) doesn't start at all. I should also clarify that I observe this in a docker container inside a kubernetes pod.

Also, I cannot reproduce it running same script in CLI (even with opcache.enable_cli => On).

In answer to the second question:

php -i | grep "jit"
auto_globals_jit => On => On
pcre.jit => 1 => 1
opcache.jit => tracing => tracing
opcache.jit_bisect_limit => 0 => 0
opcache.jit_blacklist_root_trace => 16 => 16
opcache.jit_blacklist_side_trace => 8 => 8
opcache.jit_buffer_size => 0 => 0
opcache.jit_debug => 0 => 0
opcache.jit_hot_func => 127 => 127
opcache.jit_hot_loop => 64 => 64
opcache.jit_hot_return => 8 => 8
opcache.jit_hot_side_exit => 8 => 8
opcache.jit_max_exit_counters => 8192 => 8192
opcache.jit_max_loop_unrolls => 8 => 8
opcache.jit_max_polymorphic_calls => 2 => 2
opcache.jit_max_recursive_calls => 2 => 2
opcache.jit_max_recursive_returns => 2 => 2
opcache.jit_max_root_traces => 1024 => 1024
opcache.jit_max_side_traces => 128 => 128
opcache.jit_prof_threshold => 0.005 => 0.005

@cmb69
Copy link
Member
cmb69 commented Feb 24, 2022

opcache.jit_buffer_size => 0 => 0

So OPcache JIT is disabled. I have no idea how to proceed here; maybe someone else has.

@iluuu1994
Copy link
Member

I also tried reproducing this, to no avail.

I would be happy to, and I have the coredump file, but when I compiled php with the --enable-debug flag, my application no longer runs

The assertion hints at z holding an unexpected value. You could place a breakpoint at that line and check what z->u1.v.type returns. According to that assert it should be < IS_STRING (6), so a primitive zval with no additional data.

@janedbal
Copy link

We are meeting very similar issue. Disabling opcache helps.

@janedbal
Copy link
janedbal commented Mar 28, 2022

Seems like even disabling preloading helps in our case.

@github-actions
Copy link

No feedback was provided. The issue is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so. Thank you.

@iluuu1994
Copy link
Member

Thanks for the hint, I can reproduce it with preloading.

iluuu1994 added a commit to iluuu1994/php-src that referenced this issue Apr 14, 2022
iluuu1994 added a commit to iluuu1994/php-src that referenced this issue Apr 14, 2022
@janedbal
Copy link

Thanks!

@olsavmic
Copy link
Contributor

Just for the record, we're experiencing really strange errors after re-enabling preloading on PHP 8.1.6, as if the memory was somehow messed up:

return BillingType::tryFrom($value);

where BillingType is regular backed enum:

enum BillingType: string
{
    case Terms = 'terms';
    case Prepaid = 'prepaid';
}

fails on following error:
Fulfillment\CommonBundle\Utils\EnumHelper::create(): Return value must be of type BackedEnum, Doctrine\ORM\Id\IdentityGenerator returned, which does not make any sense.

We're still using the same preloading configuration which worked before transitioning from constants to enums and the code works just fine with preloading disabled.

I'll try to create a reproducible case and submit a new issue, I just wanted to warn others about possible problems for now.

@cmb69
Copy link
Member
cmb69 commented May 20, 2022

@olsavmic, yes, please file a new ticket. :)

@php php deleted a comment from bantuan11 May 23, 2022
@iluuu1994
Copy link
Member

@olsavmic You never created an issue for this, are you still experiencing this problem?

@olsavmic
Copy link
Contributor

@iluuu1994 Yes, the issue still occurs, we're running with preloading disabled. I was just not able to create a reproducible test case nor extract some insightful logs as I was quite busy for the past week (and will be for the week to come).

If you're fine with creating an open issue with no more details than those I posted to this channel, I'll create the issue offhand :)

@iluuu1994
Copy link
Member

@olsavmic It can also wait until you have more information, I just wanted to confirm this is still an issue. 🙂 Thanks for your response.

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

No branches or pull requests

7 participants
@iluuu1994 @janedbal @cmb69 @olsavmic @alshenetsky and others