Skip to content

Commit dcca008

Browse files
authored
Allow specifying datadog.loader.force_inject=1 in loader (#3278)
* Allow specifying datadog.loader.force_inject=1 in loader Signed-off-by: Bob Weinand <[email protected]> * INI compatibility for 7.0 to 7.2 Signed-off-by: Bob Weinand <[email protected]> * Do not project too far into the future, i.e. support only PHP+1 for ini registering Signed-off-by: Bob Weinand <[email protected]> --------- Signed-off-by: Bob Weinand <[email protected]>
1 parent cbf2266 commit dcca008

File tree

3 files changed

+96
-5
lines changed

3 files changed

+96
-5
lines changed

loader/compat_php.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,27 @@ void ddloader_restore_zend_error_cb();
1414
zval *ddloader_zend_hash_update(HashTable *ht, zend_string *key, zval *pData);
1515
bool ddloader_zend_ini_parse_bool(zend_string *str);
1616

17+
#if PHP_VERSION_ID < 80000
18+
typedef int zend_result;
19+
#endif
20+
21+
typedef struct {
22+
const char *name;
23+
ZEND_INI_MH((*on_modify));
24+
void *mh_arg1;
25+
void *mh_arg2;
26+
void *mh_arg3;
27+
const char *value;
28+
void (*displayer)(zend_ini_entry *ini_entry, int type);
29+
int modifiable;
30+
31+
uint name_length;
32+
uint value_length;
33+
} php7_0_to_2_zend_ini_entry_def;
34+
35+
#undef ZEND_INI_ENTRY3_EX
36+
#define ZEND_INI_ENTRY3_EX(_name, _default_value, _modifiable, _on_modify, _arg1, _arg2, _arg3, _displayer) \
37+
{ .name = _name, .on_modify = _on_modify, .mh_arg1 = _arg1, .mh_arg2 = _arg2, .mh_arg3 = _arg3, .value = _default_value, .displayer = _displayer, .modifiable = _modifiable, .name_length = sizeof(_name)-1, .value_length = sizeof(_default_value)-1 },
38+
39+
1740
#endif /* DD_LIBRARY_LOADER_COMPAT_PHP_H */

loader/dd_library_loader.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
#define MIN_API_VERSION 320151012
1919
#define MAX_API_VERSION 420240924
20+
#define MAX_INI_API_VERSION MAX_API_VERSION + 1
2021

2122
#define PHP_70_VERSION 20151012
2223
#define PHP_71_VERSION 20160303
24+
#define PHP_72_VERSION 20170718
2325
#define PHP_80_VERSION 20200930
2426

2527
#define MIN_PHP_VERSION "7.0"
@@ -44,6 +46,28 @@ static bool already_done = false;
4446
# define OS_PATH "linux-gnu/"
4547
#endif
4648

49+
static ZEND_INI_MH(ddloader_OnUpdateForceInject) {
50+
(void)entry;
51+
(void)mh_arg1;
52+
(void)mh_arg2;
53+
(void)mh_arg3;
54+
(void)stage;
55+
56+
if (!force_load) {
57+
force_load = ddloader_zend_ini_parse_bool(new_value);
58+
}
59+
return SUCCESS;
60+
}
61+
62+
PHP_INI_BEGIN()
63+
ZEND_INI_ENTRY("datadog.loader.force_inject", "0", PHP_INI_SYSTEM, ddloader_OnUpdateForceInject)
64+
PHP_INI_END()
65+
66+
static const php7_0_to_2_zend_ini_entry_def ini_entries_7_0_to_2[] = {
67+
ZEND_INI_ENTRY("datadog.loader.force_inject", "0", PHP_INI_SYSTEM, ddloader_OnUpdateForceInject)
68+
PHP_INI_END()
69+
70+
4771
static void ddloader_telemetryf(telemetry_reason reason, injected_ext *config, const char *error, const char *format, ...);
4872

4973
static char *ddtrace_pre_load_hook(injected_ext *config) {
@@ -752,6 +776,9 @@ static int ddloader_api_no_check(int api_no) {
752776
return SUCCESS;
753777
}
754778

779+
// api_no is the Zend extension API number, similar to "420220829"
780+
// It is an int, but represented as a string, we must remove the first char to get the PHP module API number
781+
unsigned int module_api_no = api_no % 100000000;
755782
ddloader_configure();
756783

757784
TELEMETRY(REASON_START, NULL, NULL, "Starting injection");
@@ -793,6 +820,11 @@ static int ddloader_api_no_check(int api_no) {
793820
return SUCCESS;
794821
}
795822

823+
if (force_load || api_no <= MAX_INI_API_VERSION) {
824+
zend_module_entry *mod = zend_register_internal_module(&dd_library_loader_mod);
825+
zend_register_ini_entries(module_api_no <= PHP_72_VERSION ? (zend_ini_entry_def *) ini_entries_7_0_to_2 : ini_entries, mod->module_number);
826+
}
827+
796828
if (api_no > MAX_API_VERSION) {
797829
if (!force_load) {
798830
TELEMETRY(REASON_INCOMPATIBLE_RUNTIME, NULL, NULL, "Found incompatible runtime (api no: %d). Supported runtimes: PHP " MIN_PHP_VERSION " to " MAX_PHP_VERSION, api_no);
@@ -802,9 +834,7 @@ static int ddloader_api_no_check(int api_no) {
802834
LOG(NULL, WARN, "DD_INJECT_FORCE enabled, allowing unsupported runtimes and continuing (api no: %d).", api_no);
803835
}
804836

805-
// api_no is the Zend extension API number, similar to "420220829"
806-
// It is an int, but represented as a string, we must remove the first char to get the PHP module API number
807-
php_api_no = api_no % 100000000;
837+
php_api_no = module_api_no;
808838

809839
return SUCCESS;
810840
}
@@ -846,7 +876,6 @@ static int ddloader_build_id_check(const char *build_id) {
846876
// Required. Otherwise the zend_extension is not loaded
847877
static int ddloader_zend_extension_startup(zend_extension *ext) {
848878
UNUSED(ext);
849-
zend_register_internal_module(&dd_library_loader_mod);
850879
return SUCCESS;
851880
}
852881

loader/tests/functional/test_incompatibility_jit.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
EOT
106106
],
107107
],
108-
// JIT enabled + force injection
108+
// JIT enabled + force injection via ENV
109109
[
110110
"config" => "-dzend_extension=opcache -dopcache.enable_cli=1 -ddatadog.trace.cli_enabled=1 -dopcache.jit_buffer_size=32M -dopcache.jit=tracing",
111111
"env" => ['DD_INJECT_FORCE=1'],
@@ -139,6 +139,45 @@
139139
Injection error =>
140140
Extra config => datadog.trace.sources_path=%s/trace/src
141141
142+
%A
143+
OPcache JIT is enabled and may cause instability. Ignoring as DD_INJECT_FORCE is enabled
144+
%A
145+
EOT
146+
],
147+
],
148+
// JIT enabled + force injection via INI
149+
[
150+
"config" => "-dzend_extension=opcache -dopcache.enable_cli=1 -ddatadog.trace.cli_enabled=1 -ddatadog.loader.force_inject=1 -dopcache.jit_buffer_size=32M -dopcache.jit=tracing",
151+
"must_not_contain" => [],
152+
"must_contain" => [
153+
$msg_forced,
154+
<<<EOT
155+
ddtrace.disable: NO
156+
opcache_enabled: YES
157+
jit.enabled: YES
158+
jit.on: YES
159+
jit.buffer_size: 33554416
160+
EOT
161+
,
162+
<<<EOT
163+
[ddtrace] [debug] Notifying profiler of finished local root span.
164+
[ddtrace] [span] Encoding span
165+
EOT
166+
],
167+
"must_match" => [<<<EOT
168+
%A
169+
dd_library_loader_mod
170+
171+
=> Datadog Library Loader
172+
Version => %s
173+
Author => Datadog
174+
175+
=> ddtrace
176+
Version => %s
177+
Injection success => true
178+
Injection error =>
179+
Extra config => datadog.trace.sources_path=%s/trace/src
180+
142181
%A
143182
OPcache JIT is enabled and may cause instability. Ignoring as DD_INJECT_FORCE is enabled
144183
%A

0 commit comments

Comments
 (0)