symfony / polyfill

PHP polyfills

Home Page:https://symfony.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Symfony Polyfill Uuid inoperative under Opcache Preloading

SebastienTainon opened this issue · comments

Symfony version(s) affected: 4.4

Description
At first I was simply trying to understand why my Sentry errors weren't sent in my prod environment like there were sent on my dev environment. I realized Sentry was returning "400 Bad Request" because the eventId property was not send. This eventId is an UUID that is created using uuid_create(UUID_TYPE_RANDOM) in this file: https://github.com/getsentry/sentry-php/blob/master/src/Event.php
They've recently replaced ramsey/uuid with "uuid_create from the PECL extension or symfony/polyfill-uuid": getsentry/sentry-php@bfb2a40
Ok, fair enough. But that piece of code returned nothing, because UUID_TYPE_RANDOM was not defined, though it should be by polyfill just here: https://github.com/symfony/polyfill-uuid/blob/master/bootstrap.php
After some more hours of investigation, I realized the reason why that didn't work on my prod environment was because I had PHP 7.4 Opcache Preloading enabled. If I disable the preloading, everything works fine (the polyfill, the UUID generation, the Sentry event...).

What I suspect is that when Opcache preloading is on, the uuid_create function gets preloaded into Opcache, and the if (!function_exists('uuid_create')) { is then false, so the polyfill is not executed, thus UUID_TYPE_RANDOM is not defined and consequently the uuid_create(UUID_TYPE_RANDOM) does not work, (and the eventId is not sent, and Sentry sends 400 Bad Request... long story...).

How to reproduce

  1. composer require symfony/polyfill-uuid
  2. Enable opcache preloading with php7.4
  3. var_dump(uuid_create(UUID_TYPE_RANDOM))

Possible Solution
I guess we shouldn't do the check on the existence of only the uuid_create but rather on the existence of each individual constant and function. I'm available to do a PR on this, let me know if necessary.

Temporary fix
If anyone else has this issue, I simply added the following code to my config/bootstrap.php file to define the missing constant until symfony/polyfill-uuid is fixed:

if (!defined('UUID_TYPE_RANDOM')) {
    define('UUID_TYPE_RANDOM', 4);
}

Thanks for the report.
I'd suggest splitting all constant definition in a separate file - actually in two separate files: one using define() for PHP5, another using const for PHP7+.
We should do so for all components.
Up for a PR?

Well, is it worth maintaining 2 files defining the same constants ? Or would const be preloadable ?

would const be preloadable

yes! that's why I suggested this strategy.

/cc @nikic WDYT about this?

would const be preloadable

according to @azjezz that's not the case, so: no need for a separate file - we should group calls to define() under separate main defined() checks.

Hello @nicolas-grekas, thanks for the quick response!

I've tried #239 and I can confirm that it solves my problem 👍