Skip to content

Commit

Permalink
Don't inject the tracer if Opcache JIT is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
iamluc committed Sep 17, 2024
1 parent 4f3fc2b commit 5d19319
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 3 deletions.
57 changes: 54 additions & 3 deletions loader/dd_library_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
#endif

#include <Zend/zend_extensions.h>
#include <Zend/zend_ini.h>
#include <php.h>
#include <php_ini.h>
#include <stdbool.h>
#include <main/SAPI.h>
#include <ext/standard/basic_functions.h>

#include "compat_php.h"
Expand Down Expand Up @@ -68,16 +70,65 @@ static bool ddloader_is_ext_loaded(const char *name) {
;
}

static bool ddtrace_compat_check_hook(void) {
static zval *ddloader_ini_get_configuration(const char *name, size_t name_len) {
HashTable *configuration_hash = php_ini_get_configuration_hash();
if (!configuration_hash) {
return NULL;
}
zend_string *ini = ddloader_zend_string_init(php_api_no, name, name_len, 1);
zval *val = zend_hash_find(configuration_hash, ini);
ddloader_zend_string_release(php_api_no, ini);

return val;
}

static bool ddtrace_compat_check_hook() {
char *incompatible_exts[] = {"Xdebug", "the ionCube PHP Loader", "newrelic", "blackfire", "pcov"};
for (size_t i = 0; i < sizeof(incompatible_exts) / sizeof(incompatible_exts[0]); ++i) {
if (ddloader_is_ext_loaded(incompatible_exts[i])) {
TELEMETRY(REASON_INCOMPATIBLE_RUNTIME, "Incompatible extension '%s' detected, unregister the injected extension", incompatible_exts[i]);
if (!force_load) {
TELEMETRY(REASON_INCOMPATIBLE_RUNTIME, "Incompatible extension '%s' detected, unregister the injected extension", incompatible_exts[i]);
return false;
}
LOG(WARN, "Incompatible extension '%s' detected, continuing as DD_INJECT_FORCE is enabled", incompatible_exts[i]);
}
}

return false;
// Check if JIT (PHP 8.0+) is enabled
if (php_api_no < 20200930 || !ddloader_is_ext_loaded("Zend OPcache")) {
return true;
}
zval *opcache_enable = ddloader_ini_get_configuration(ZEND_STRL("opcache.enable"));
if (opcache_enable && Z_TYPE_P(opcache_enable) == IS_STRING && !zend_ini_parse_bool(Z_STR_P(opcache_enable))) {
return true;
}
if (strcmp("cli", sapi_module.name) == 0) {
zval *opcache_enable_cli = ddloader_ini_get_configuration(ZEND_STRL("opcache.enable_cli"));
if (!opcache_enable_cli || Z_TYPE_P(opcache_enable_cli) != IS_STRING || !zend_ini_parse_bool(Z_STR_P(opcache_enable_cli))) {
return true;
}
}
if (php_api_no > 20230831) { // PHP > 8.3 (https://php.watch/versions/8.4/opcache-jit-ini-default-changes)
zval *opcache_jit = ddloader_ini_get_configuration(ZEND_STRL("opcache.jit"));
if (opcache_jit && Z_TYPE_P(opcache_jit) == IS_STRING && strcmp(Z_STRVAL_P(opcache_jit), "disable") != 0 && strcmp(Z_STRVAL_P(opcache_jit), "off") != 0) {
goto jit_enabled;
}
} else {
zval *opcache_jit_buffer_size = ddloader_ini_get_configuration(ZEND_STRL("opcache.jit_buffer_size"));
if (opcache_jit_buffer_size && Z_TYPE_P(opcache_jit_buffer_size) == IS_STRING && strcmp(Z_STRVAL_P(opcache_jit_buffer_size), "0") != 0) {
goto jit_enabled;
}
}

return true;

jit_enabled:
if (!force_load) {
TELEMETRY(REASON_INCOMPATIBLE_RUNTIME, "Opcache JIT is enabled, unregister the injected extension");
return false;
}
LOG(WARN, "Opcache JIT is enabled, continuing as DD_INJECT_FORCE is enabled");

return true;
}

Expand Down
7 changes: 7 additions & 0 deletions loader/tests/functional/includes/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ function skip_if_not_php5() {
}
}

function skip_if_not_php8() {
if (PHP_MAJOR_VERSION < 8) {
echo "Skip: test requires PHP 8\n";
exit(0);
}
}

function skip_if_opcache_missing() {
$output = runCLI('-dzend_extension=opcache -m');
if (strpos($output, 'Zend OPcache') === false) {
Expand Down
28 changes: 28 additions & 0 deletions loader/tests/functional/test_incompatibility_jit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

require_once __DIR__."/includes/autoload.php";
skip_if_not_php8();
skip_if_opcache_missing();

$jit_disabled = [
"-dzend_extension=opcache",
"-dzend_extension=opcache -dopcache.jit_buffer_size=32M",
"-dzend_extension=opcache -dopcache.jit_buffer_size=32M -dopcache.enable=0 -dopcache.enable_cli=1",
"-dzend_extension=opcache -dopcache.jit=tracing -dopcache.enable_cli=1",
];
foreach ($jit_disabled as $options) {
$output = runCLI($options.' -v', true, ['DD_TRACE_DEBUG=1']);
assertContains($output, 'Application instrumentation bootstrapping complete (\'ddtrace\')');
assertContains($output, 'with dd_library_loader v');
assertContains($output, 'with ddtrace v');
}

$jit_enabled = [
"-dzend_extension=opcache -dopcache.jit_buffer_size=32M -dopcache.enable_cli=1",
];
foreach ($jit_enabled as $options) {
$output = runCLI($options.' -v', true, ['DD_TRACE_DEBUG=1']);
assertContains($output, 'Opcache JIT is enabled, unregister the injected extension');
assertContains($output, 'with dd_library_loader v');
assertNotContains($output, 'with ddtrace v');
}

0 comments on commit 5d19319

Please sign in to comment.