Skip to content

Commit f7328a8

Browse files
authored
Block remote config signals during ftp functions (#2957)
* Reduce the amount of diagnostic messages sent Done by deduplicating them. Signed-off-by: Bob Weinand <[email protected]> Handle case where the applictaion is stopped without other telemetry sent This lead down to a path where the Stop action was actually enqueued without being ever causing a removal of the Application instances. Signed-off-by: Bob Weinand <[email protected]> * Fix appsec format Signed-off-by: Bob Weinand <[email protected]> * Block remote config signals during ftp functions These are sensitive to EINTR, so block the signal during their execution. Fixes #2952. Signed-off-by: Bob Weinand <[email protected]> * Avoid redundant signal checking on linux Signed-off-by: Bob Weinand <[email protected]> --------- Signed-off-by: Bob Weinand <[email protected]>
1 parent a00605d commit f7328a8

11 files changed

+155
-7
lines changed

Cargo.lock

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

appsec/src/extension/configuration.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,11 @@ static void _register_testing_objects(void);
216216

217217
bool dd_config_minit(int module_number)
218218
{
219-
// We have to disable remote config by default on lambda due to issues with the sidecar there. We'll eventually fix it though.
219+
// We have to disable remote config by default on lambda due to issues with
220+
// the sidecar there. We'll eventually fix it though.
220221
if (getenv("AWS_LAMBDA_FUNCTION_NAME")) {
221-
config_entries[DDAPPSEC_CONFIG_DD_REMOTE_CONFIG_ENABLED].default_encoded_value = (zai_str) ZAI_STR_FROM_CSTR("false");
222+
config_entries[DDAPPSEC_CONFIG_DD_REMOTE_CONFIG_ENABLED]
223+
.default_encoded_value = (zai_str)ZAI_STR_FROM_CSTR("false");
222224
}
223225

224226
if (!zai_config_minit(config_entries,

components-rs/ddtrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ struct ddog_RemoteConfigState *ddog_init_remote_config_state(const struct ddog_E
171171

172172
const char *ddog_remote_config_get_path(const struct ddog_RemoteConfigState *remote_config);
173173

174-
void ddog_process_remote_configs(struct ddog_RemoteConfigState *remote_config);
174+
bool ddog_process_remote_configs(struct ddog_RemoteConfigState *remote_config);
175175

176176
bool ddog_type_can_be_instrumented(const struct ddog_RemoteConfigState *remote_config,
177177
ddog_CharSlice typename_);

components-rs/remote_config.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use datadog_remote_config::{
1414
use datadog_sidecar::service::blocking::SidecarTransport;
1515
use datadog_sidecar::service::{InstanceId, QueueId};
1616
use datadog_sidecar::shm_remote_config::{RemoteConfigManager, RemoteConfigUpdate};
17-
use datadog_sidecar_ffi::ddog_sidecar_send_debugger_data;
17+
use datadog_sidecar_ffi::{ddog_sidecar_send_debugger_data, ddog_sidecar_send_debugger_diagnostics};
1818
use ddcommon::Endpoint;
1919
use ddcommon_ffi::slice::AsBytes;
2020
use ddcommon_ffi::{CharSlice, MaybeError};
@@ -243,7 +243,8 @@ pub extern "C" fn ddog_remote_config_get_path(remote_config: &RemoteConfigState)
243243
}
244244

245245
#[no_mangle]
246-
pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigState) {
246+
pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigState) -> bool {
247+
let mut has_updates = false;
247248
loop {
248249
match remote_config.manager.fetch_update() {
249250
RemoteConfigUpdate::None => break,
@@ -292,7 +293,9 @@ pub extern "C" fn ddog_process_remote_configs(remote_config: &mut RemoteConfigSt
292293
_ => (),
293294
},
294295
}
296+
has_updates = true
295297
}
298+
has_updates
296299
}
297300

298301
fn apply_config(
@@ -531,5 +534,6 @@ pub unsafe extern "C" fn ddog_send_debugger_diagnostics<'a>(
531534
"Submitting debugger diagnostics data: {:?}",
532535
serde_json::to_string(&payload).unwrap()
533536
);
534-
ddog_sidecar_send_debugger_data(transport, instance_id, queue_id, vec![payload])
537+
538+
ddog_sidecar_send_debugger_diagnostics(transport, instance_id, queue_id, payload)
535539
}

components-rs/sidecar.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ ddog_MaybeError ddog_sidecar_send_debugger_datum(struct ddog_SidecarTransport **
223223
ddog_QueueId queue_id,
224224
struct ddog_DebuggerPayload *payload);
225225

226+
ddog_MaybeError ddog_sidecar_send_debugger_diagnostics(struct ddog_SidecarTransport **transport,
227+
const struct ddog_InstanceId *instance_id,
228+
ddog_QueueId queue_id,
229+
struct ddog_DebuggerPayload diagnostics_payload);
230+
226231
ddog_MaybeError ddog_sidecar_set_remote_config_data(struct ddog_SidecarTransport **transport,
227232
const struct ddog_InstanceId *instance_id,
228233
const ddog_QueueId *queue_id,

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ if test "$PHP_DDTRACE" != "no"; then
184184
ext/handlers_exception.c \
185185
ext/handlers_internal.c \
186186
ext/handlers_pcntl.c \
187+
ext/handlers_signal.c \
187188
ext/integrations/exec_integration.c \
188189
ext/integrations/integrations.c \
189190
ext/ip_extraction.c \

ext/handlers_internal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ void ddtrace_free_unregistered_class(zend_class_entry *ce) {
3030
void ddtrace_curl_handlers_startup(void);
3131
void ddtrace_exception_handlers_startup(void);
3232
void ddtrace_pcntl_handlers_startup(void);
33+
#ifndef _WIN32
34+
void ddtrace_signal_block_handlers_startup(void);
35+
#endif
3336

3437
#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80200
3538
#include <hook/hook.h>
@@ -147,6 +150,10 @@ void ddtrace_internal_handlers_startup() {
147150
ddtrace_exception_handlers_startup();
148151

149152
ddtrace_exec_handlers_startup();
153+
#ifndef _WIN32
154+
// Block remote-config signals of some functions
155+
ddtrace_signal_block_handlers_startup();
156+
#endif
150157
}
151158

152159
void ddtrace_internal_handlers_shutdown(void) {

ext/handlers_signal.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "handlers_api.h"
2+
#include "remote_config.h"
3+
#include <signal.h>
4+
#include <php.h>
5+
6+
/* We need to do signal blocking for the remote config signaling to not interfere with some PHP functions.
7+
* See e.g. https://github.com/php/php-src/issues/16800
8+
* I don't know the full problem space, so I expect there might be functions missing here, and we need to eventually expand this list.
9+
*/
10+
static void dd_handle_signal(zif_handler original_function, INTERNAL_FUNCTION_PARAMETERS) {
11+
sigset_t x;
12+
sigemptyset(&x);
13+
sigaddset(&x, SIGVTALRM);
14+
sigprocmask(SIG_BLOCK, &x, NULL);
15+
16+
original_function(INTERNAL_FUNCTION_PARAM_PASSTHRU);
17+
18+
sigprocmask(SIG_UNBLOCK, &x, NULL);
19+
#ifndef __linux__
20+
// At least on linux unblocking causes immediate signal delivery.
21+
ddtrace_check_for_new_config_now();
22+
#endif
23+
}
24+
25+
#define BLOCKSIGFN(function) \
26+
static zif_handler dd_handle_signal_zif_##function;\
27+
static ZEND_FUNCTION(dd_handle_signal_##function) { \
28+
dd_handle_signal(dd_handle_signal_zif_##function, INTERNAL_FUNCTION_PARAM_PASSTHRU); \
29+
}
30+
31+
#define BLOCK(x) \
32+
x(ftp_alloc) \
33+
x(ftp_append) \
34+
x(ftp_cdup) \
35+
x(ftp_chdir) \
36+
x(ftp_chmod) \
37+
x(ftp_close) \
38+
x(ftp_connect) \
39+
x(ftp_delete) \
40+
x(ftp_exec) \
41+
x(ftp_fget) \
42+
x(ftp_fput) \
43+
x(ftp_get) \
44+
x(ftp_get_option) \
45+
x(ftp_login) \
46+
x(ftp_mdtm) \
47+
x(ftp_mkdir) \
48+
x(ftp_mlsd) \
49+
x(ftp_nb_continue) \
50+
x(ftp_nb_fget) \
51+
x(ftp_nb_fput) \
52+
x(ftp_nb_get) \
53+
x(ftp_nb_put) \
54+
x(ftp_nlist) \
55+
x(ftp_pasv) \
56+
x(ftp_put) \
57+
x(ftp_pwd) \
58+
x(ftp_quit) \
59+
x(ftp_raw) \
60+
x(ftp_rawlist) \
61+
x(ftp_rename) \
62+
x(ftp_rmdir) \
63+
x(ftp_site) \
64+
x(ftp_size) \
65+
x(ftp_ssl_connect) \
66+
x(ftp_systype) \
67+
68+
BLOCK(BLOCKSIGFN)
69+
70+
void ddtrace_signal_block_handlers_startup() {
71+
#define BLOCKFNENTRY(function) { ZEND_STRL(#function), &dd_handle_signal_zif_##function, ZEND_FN(dd_handle_signal_##function) },
72+
datadog_php_zif_handler handlers[] = { BLOCK(BLOCKFNENTRY) };
73+
74+
size_t handlers_len = sizeof handlers / sizeof handlers[0];
75+
for (size_t i = 0; i < handlers_len; ++i) {
76+
datadog_php_install_handler(handlers[i]);
77+
}
78+
}

ext/remote_config.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ DDTRACE_PUBLIC void ddtrace_set_all_thread_vm_interrupt(void) {
5757
#endif
5858
}
5959

60+
void ddtrace_check_for_new_config_now(void) {
61+
if (DDTRACE_G(remote_config_state) && !DDTRACE_G(reread_remote_configuration) && ddog_process_remote_configs(DDTRACE_G(remote_config_state))) {
62+
// If we blocked the signal, notify the other threads too
63+
ddtrace_set_all_thread_vm_interrupt();
64+
}
65+
}
66+
6067
DDTRACE_PUBLIC const char *ddtrace_remote_config_get_path() {
6168
if (DDTRACE_G(remote_config_state)) {
6269
return ddog_remote_config_get_path(DDTRACE_G(remote_config_state));

ext/remote_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ void ddtrace_minit_remote_config(void);
77
void ddtrace_mshutdown_remote_config(void);
88
void ddtrace_rinit_remote_config(void);
99
void ddtrace_rshutdown_remote_config(void);
10+
void ddtrace_check_for_new_config_now(void);
11+
1012

1113
DDTRACE_PUBLIC void ddtrace_set_all_thread_vm_interrupt(void);
1214
DDTRACE_PUBLIC const char *ddtrace_remote_config_get_path(void);

0 commit comments

Comments
 (0)