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

Modify agent to conform with new PHP 8.0 internal API changes #49

Merged
merged 25 commits into from
Dec 17, 2020
Merged

Modify agent to conform with new PHP 8.0 internal API changes #49

merged 25 commits into from
Dec 17, 2020

Conversation

zsistla
Copy link
Contributor

@zsistla zsistla commented Dec 9, 2020

Items addressed:

  1. Added defines for PHP8
  2. Added TSRMLS_* macros (these have been voided out in php-src since PHP7.0, but were officially removed in PHP8.0)
  3. The Object Handlers API was changed to receive zend_object* instead of zval* and zend_string* instead of zval* for property names. Modified agent to toggle between zval and zend_object depending on PHP8 or not.
  4. The zend_fcall_info no_separation flag has been removed, and separation is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
  5. Error notifications have a new API and the callback signature has changed. The current changes do not register a callback.
  6. display_disabled_function has been removed from (and therefore zif_display_disabled_function) zend_API.c.. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
  7. Added newrelic_arginfo_void as PHP_FE no longer allows 0 as an argument.
  8. Necessary changes to allow agent tests to compile.
  9. Take into account new libphp.so and libphp.a naming scheme.
  10. With PHP8, call_user_function_ex was removed and call_user_function
  • became the recommended function; however, the call handles param_values
  • differently. Prior to PHP8, we used the no_separation flag set to 0 which
  • then did some internal manipulation of param_values. There is no longer a
  • no separation flag, so that internal manipulation is no longer done and we
  • need to do it prior to sending param_values or call_user_function will
  • cause a segfault.
  1. zend_get_resource_handle now takes a different type parameter.

Remaining items:

  1. Regarding changing call_user_function_ex call to the call_user_function call in the agent function nr_php_call_user_func:
    With call_user_function_ex, we used to use the no_separation flag = 0, which meant PHP itself would internally manipulate ours args appropriately.

With call_user_function the logic has changed here:
https://github.com/php/php-src/blob/master/Zend/zend_execute_API.c#L770

Currently any UNIT TEST call to nr_php_call or a direct call to nr_php_call_user_func that has parameters will choke because the internal handling no longer wraps them as proper zval refs.

Before we pass the params to PHP function call_user_function, we probably need to do something like:

if (!Z_ISREF_P(arg)) {
 nrl_verbosedebug(NRL_AGENT, "debug22: adding ref");
 Z_TRY_ADDREF_P(arg);
 ZVAL_NEW_REF(arg, arg);
}

This code could either be placed directly in the nr_php_call_user_func function or be an inline function declared in php_zval.h like:

static inline void nr_php_zval_wrap_out_arg(zval* zv) {
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */
  if (!Z_ISREF_P(zv)) {
    Z_TRY_ADDREF_P(arg);
    ZVAL_NEW_REF(zv, zv);
  }
#endif
}
  1. Additionally, calls to call_user_func_array have changed (as evidenced by this https://www.drupal.org/project/drupal/issues/3174022 discussion), and we still need to ensure any tests and/or wrappers handle it accordingly.

  2. The API internals ticket still has a few allocated days left for someone to pick up.

  3. The unit tests will need to be updated to take into account the changes.

Fixes #46

… of zval* and zend_string* instead of zval* for property names. Modified agent to toggle between zval and zend_object depending on PHP8 or not.
…on is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
…nged. The current changes do not register a callback.
…_function`) has been removed `zend_API.c.`. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
…he recommended function; however, it no longer gracefully handled the case of the 2nd parameter being passed in as NULL. We no longer assume graceful handling, and now we check for NULL before calling the function.
agent/php_call.c Outdated Show resolved Hide resolved
Comment on lines 13 to 14
#if ZEND_MODULE_API_NO >= ZEND_7_0_X_API_NO /* PHP 7.0+ */
#define PHP7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We updated our usages of PHP7 to use the more complex ifdef in order to make it clear we were referring to PHP version 7.0 or greater. This define doesn't allow for us to target things just to PHP 7 (and not 8 or 5). Should we update this definition to exclude PHP 8?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if we are sure we've replaced all PHP7 ifdefs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still a bunch of PHP7 ifdefs left. I filed issue #56 to track the need to clean up our ifdef usage so it doesn't block this PR.

agent/php_zval.h Outdated Show resolved Hide resolved
@joshuabenuck
Copy link
Contributor

ok jenkins

@@ -1,4 +1,4 @@
#!/bin/bash
make -j $(nproc) all
make -j $(nproc) run_tests
make -j run_tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I never knew about -j without any flags 🧠

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes two of us! That was a typo, but apparently -j without flags is a thing!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I thought it was intentional for maximum test pedal to the metal 😆

Comment on lines +724 to +730
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */
/* PHP 8 expects zend_object not zval */
#define ZVAL_OR_ZEND_OBJECT(x) Z_OBJ(*x)
#else
#define ZVAL_OR_ZEND_OBJECT(x) x
#endif /* PHP8+ */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

/*
* The TSRMLS_* functions included below have actually been voided out since PHP
* 7.0. They were formally removed in PHP 8.0 but we still support in our code,
* so we need to add the voided out macros here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect solution!

Comment on lines +130 to +132
#ifdef PHP8
add_assoc_zval(arr, key, &copy);
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context in case anyone else was confused by this

php/php-src/pull/5805

…ound definition of `newrelic_arginfo_void` since all usages of this were also wrapped in PHP 8 `if` statements which would then result in an used arg error/warning on some builds.
@zsistla
Copy link
Contributor Author

zsistla commented Dec 17, 2020

ok jenkins

1 similar comment
@joshuabenuck
Copy link
Contributor

ok jenkins

@joshuabenuck joshuabenuck merged commit ed1aec7 into newrelic:main Dec 17, 2020
@zsistla zsistla added the enhancement New feature or request label Jan 20, 2021
joshuabenuck pushed a commit to joshuabenuck/newrelic-php-agent that referenced this pull request Feb 16, 2021
…ic#49)

Fixes newrelic#46 

* Added defines for PHP8.
* Added `TSRMLS` macros.
* The Object Handlers API was changed to receive zend_object* instead of zval* and zend_string* instead of zval* for property names.  Modified agent to toggle between zval and zend_object depending on PHP8 or not.
* The zend_fcall_info no_separation flag has been removed, and separation is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
* Error notifications have a new API and the callback signature has changed. The current changes do not register a callback.
* `display_disabled_function` (and therefore also `zif_display_disabled_function`) has been removed `zend_API.c.`. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
* Added `newrelic_arginfo_void` as `PHP_FE` no longer allows `0` as an argument.
* Modified unit tests to work with PHP8.
* `call_user_function_ex` was removed and `call_user_function` became the recommended function; however, it no longer gracefully handled the case of the 2nd parameter  being passed in as NULL. We no longer assume graceful handling, and now we check for NULL before calling the function.
* Take into account new `libphp.so` and `libphp.a` naming scheme.
* `zend_get_resource_handle` now takes a different type parameter.
* Added `#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */` around definition of `newrelic_arginfo_void` since all usages of this were also wrapped in PHP 8 `if` statements which would then result in an used arg error/warning on some builds.
* Update opcode inspection to properly detect calls to `call_user_func_array`. On PHP 8.0, there's an additional opcode added when the function is compiled.

Co-authored-by: Joshua Benuck <[email protected]>
joshuabenuck pushed a commit that referenced this pull request Feb 16, 2021
Fixes #46 

* Added defines for PHP8.
* Added `TSRMLS` macros.
* The Object Handlers API was changed to receive zend_object* instead of zval* and zend_string* instead of zval* for property names.  Modified agent to toggle between zval and zend_object depending on PHP8 or not.
* The zend_fcall_info no_separation flag has been removed, and separation is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
* Error notifications have a new API and the callback signature has changed. The current changes do not register a callback.
* `display_disabled_function` (and therefore also `zif_display_disabled_function`) has been removed `zend_API.c.`. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
* Added `newrelic_arginfo_void` as `PHP_FE` no longer allows `0` as an argument.
* Modified unit tests to work with PHP8.
* `call_user_function_ex` was removed and `call_user_function` became the recommended function; however, it no longer gracefully handled the case of the 2nd parameter  being passed in as NULL. We no longer assume graceful handling, and now we check for NULL before calling the function.
* Take into account new `libphp.so` and `libphp.a` naming scheme.
* `zend_get_resource_handle` now takes a different type parameter.
* Added `#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */` around definition of `newrelic_arginfo_void` since all usages of this were also wrapped in PHP 8 `if` statements which would then result in an used arg error/warning on some builds.
* Update opcode inspection to properly detect calls to `call_user_func_array`. On PHP 8.0, there's an additional opcode added when the function is compiled.

Co-authored-by: Joshua Benuck <[email protected]>
joshuabenuck pushed a commit that referenced this pull request Apr 20, 2021
Fixes #46 

* Added defines for PHP8.
* Added `TSRMLS` macros.
* The Object Handlers API was changed to receive zend_object* instead of zval* and zend_string* instead of zval* for property names.  Modified agent to toggle between zval and zend_object depending on PHP8 or not.
* The zend_fcall_info no_separation flag has been removed, and separation is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
* Error notifications have a new API and the callback signature has changed. The current changes do not register a callback.
* `display_disabled_function` (and therefore also `zif_display_disabled_function`) has been removed `zend_API.c.`. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
* Added `newrelic_arginfo_void` as `PHP_FE` no longer allows `0` as an argument.
* Modified unit tests to work with PHP8.
* `call_user_function_ex` was removed and `call_user_function` became the recommended function; however, it no longer gracefully handled the case of the 2nd parameter  being passed in as NULL. We no longer assume graceful handling, and now we check for NULL before calling the function.
* Take into account new `libphp.so` and `libphp.a` naming scheme.
* `zend_get_resource_handle` now takes a different type parameter.
* Added `#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */` around definition of `newrelic_arginfo_void` since all usages of this were also wrapped in PHP 8 `if` statements which would then result in an used arg error/warning on some builds.
* Update opcode inspection to properly detect calls to `call_user_func_array`. On PHP 8.0, there's an additional opcode added when the function is compiled.

Co-authored-by: Joshua Benuck <[email protected]>
mfulb pushed a commit to mfulb/newrelic-php-agent that referenced this pull request Sep 28, 2022
…ic#49)

Fixes newrelic#46 

* Added defines for PHP8.
* Added `TSRMLS` macros.
* The Object Handlers API was changed to receive zend_object* instead of zval* and zend_string* instead of zval* for property names.  Modified agent to toggle between zval and zend_object depending on PHP8 or not.
* The zend_fcall_info no_separation flag has been removed, and separation is never allowed. If you wish to pass (or allow passing) arguments by reference, explicitly create those arguments as references using ZEND_MAKE_REF. This function is passed as a pointer in the agent here. This removal also affects call_user_function_ex() (example in agent), which should be replaced by call_user_function().
* Error notifications have a new API and the callback signature has changed. The current changes do not register a callback.
* `display_disabled_function` (and therefore also `zif_display_disabled_function`) has been removed `zend_API.c.`. In PHP 8, a disabled function is indistinguishable from a function that does not exist.
* Added `newrelic_arginfo_void` as `PHP_FE` no longer allows `0` as an argument.
* Modified unit tests to work with PHP8.
* `call_user_function_ex` was removed and `call_user_function` became the recommended function; however, it no longer gracefully handled the case of the 2nd parameter  being passed in as NULL. We no longer assume graceful handling, and now we check for NULL before calling the function.
* Take into account new `libphp.so` and `libphp.a` naming scheme.
* `zend_get_resource_handle` now takes a different type parameter.
* Added `#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO /* PHP 8.0+ */` around definition of `newrelic_arginfo_void` since all usages of this were also wrapped in PHP 8 `if` statements which would then result in an used arg error/warning on some builds.
* Update opcode inspection to properly detect calls to `call_user_func_array`. On PHP 8.0, there's an additional opcode added when the function is compiled.

Co-authored-by: Joshua Benuck <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modify agent to conform with new PHP 8.0 internal API changes
3 participants