Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions components-rs/ddtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ ddog_MaybeError ddog_sidecar_connect_php(struct ddog_SidecarTransport **connecti
void ddtrace_sidecar_reconnect(struct ddog_SidecarTransport **transport,
struct ddog_SidecarTransport *(*factory)(void));

// Thread-based sidecar connection (Unix only)
#if !defined(_WIN32)
ddog_MaybeError ddog_sidecar_connect_master(int32_t pid);
ddog_MaybeError ddog_sidecar_connect_worker(int32_t pid,
struct ddog_SidecarTransport **connection);
ddog_MaybeError ddog_sidecar_shutdown_master_listener(void);
bool ddog_sidecar_is_master_listener_active(int32_t pid);
ddog_MaybeError ddog_sidecar_clear_inherited_listener(void);
#endif

bool ddog_shm_limiter_inc(const struct ddog_MaybeShmLimiter *limiter, uint32_t limit);

bool ddog_exception_hash_limiter_inc(struct ddog_SidecarTransport *connection,
Expand Down
38 changes: 38 additions & 0 deletions components-rs/sidecar.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,44 @@ void ddog_sidecar_transport_drop(struct ddog_SidecarTransport*);
*/
ddog_MaybeError ddog_sidecar_connect(struct ddog_SidecarTransport **connection);

/**
* Start master listener thread for thread-based connections (Unix only).
*
* This spawns a listener thread that accepts worker connections.
*/
#if !defined(_WIN32)
ddog_MaybeError ddog_sidecar_connect_master(int32_t pid);
#endif

/**
* Connect as worker to master listener thread (Unix only).
*/
#if !defined(_WIN32)
ddog_MaybeError ddog_sidecar_connect_worker(int32_t pid,
struct ddog_SidecarTransport **connection);
#endif

/**
* Shutdown the master listener thread (Unix only).
*/
#if !defined(_WIN32)
ddog_MaybeError ddog_sidecar_shutdown_master_listener(void);
#endif

/**
* Check if master listener is active for the given PID (Unix only).
*/
#if !defined(_WIN32)
bool ddog_sidecar_is_master_listener_active(int32_t pid);
#endif

/**
* Clear inherited master listener state in child after fork (Unix only).
*/
#if !defined(_WIN32)
ddog_MaybeError ddog_sidecar_clear_inherited_listener(void);
#endif

ddog_MaybeError ddog_sidecar_ping(struct ddog_SidecarTransport **transport);

ddog_MaybeError ddog_sidecar_flush_traces(struct ddog_SidecarTransport **transport);
Expand Down
1 change: 1 addition & 0 deletions components-rs/telemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub unsafe extern "C" fn ddog_sidecar_telemetry_enqueueConfig_buffer(
value: config_value.to_utf8_lossy().into_owned(),
origin,
config_id,
seq_id: None,
});
buffer.buffer.push(SidecarAction::Telemetry(action));
}
Expand Down
15 changes: 15 additions & 0 deletions ext/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ static bool dd_parse_sampling_rules_format(zai_str value, zval *decoded_value, b
return true;
}

static bool dd_parse_sidecar_connection_mode(zai_str value, zval *decoded_value, bool persistent) {
UNUSED(persistent);
if (zai_str_eq_ci_cstr(value, "auto")) {
ZVAL_LONG(decoded_value, DD_TRACE_SIDECAR_CONNECTION_MODE_AUTO);
} else if (zai_str_eq_ci_cstr(value, "subprocess")) {
ZVAL_LONG(decoded_value, DD_TRACE_SIDECAR_CONNECTION_MODE_SUBPROCESS);
} else if (zai_str_eq_ci_cstr(value, "thread")) {
ZVAL_LONG(decoded_value, DD_TRACE_SIDECAR_CONNECTION_MODE_THREAD);
} else {
return false;
}

return true;
}

static bool dd_parse_tags(zai_str value, zval *decoded_value, bool persistent) {
ZVAL_ARR(decoded_value, pemalloc(sizeof(HashTable), persistent));
zend_hash_init(Z_ARR_P(decoded_value), 8, NULL, persistent ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR, persistent);
Expand Down
7 changes: 7 additions & 0 deletions ext/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ enum ddtrace_sampling_rules_format {
DD_TRACE_SAMPLING_RULES_FORMAT_GLOB
};

enum ddtrace_sidecar_connection_mode {
DD_TRACE_SIDECAR_CONNECTION_MODE_AUTO = 0, // Default: try subprocess, fallback to thread
DD_TRACE_SIDECAR_CONNECTION_MODE_SUBPROCESS = 1, // Force subprocess only
DD_TRACE_SIDECAR_CONNECTION_MODE_THREAD = 2, // Force thread only
};

/* From the curl docs on CONNECT_TIMEOUT_MS:
* If libcurl is built to use the standard system name resolver, that
* portion of the transfer will still use full-second resolution for
Expand Down Expand Up @@ -225,6 +231,7 @@ enum ddtrace_sampling_rules_format {
CONFIG(STRING, DD_TRACE_AGENT_TEST_SESSION_TOKEN, "", .ini_change = ddtrace_alter_test_session_token) \
CONFIG(BOOL, DD_TRACE_PROPAGATE_USER_ID_DEFAULT, "false") \
CONFIG(CUSTOM(INT), DD_DBM_PROPAGATION_MODE, "disabled", .parser = dd_parse_dbm_mode) \
CONFIG(CUSTOM(INT), DD_TRACE_SIDECAR_CONNECTION_MODE, "auto", .parser = dd_parse_sidecar_connection_mode) \
CONFIG(SET, DD_TRACE_WORDPRESS_ADDITIONAL_ACTIONS, "") \
CONFIG(BOOL, DD_TRACE_WORDPRESS_CALLBACKS, "true") \
CONFIG(BOOL, DD_INTEGRATION_METRICS_ENABLED, "true", \
Expand Down
22 changes: 21 additions & 1 deletion ext/ddtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,7 @@ static PHP_MINIT_FUNCTION(ddtrace) {
#endif
ddshared_minit();
ddtrace_autoload_minit();
ddtrace_sidecar_minit();

dd_register_span_data_ce();
dd_register_fatal_error_ce();
Expand Down Expand Up @@ -1612,7 +1613,11 @@ static PHP_MSHUTDOWN_FUNCTION(ddtrace) {

ddtrace_user_req_shutdown();

ddtrace_sidecar_shutdown();
// Only shutdown sidecar in MSHUTDOWN for non-CLI SAPIs
// CLI SAPI shuts down in RSHUTDOWN to allow thread joins before ASAN checks
if (strcmp(sapi_module.name, "cli") != 0) {
ddtrace_sidecar_shutdown();
}

ddtrace_live_debugger_mshutdown();

Expand Down Expand Up @@ -2632,6 +2637,21 @@ void dd_internal_handle_fork(void) {
ddtrace_coms_curl_shutdown();
ddtrace_coms_clean_background_sender_after_fork();
}

// Handle thread mode after fork
int32_t current_pid = (int32_t)getpid();
bool is_child_process = (ddtrace_sidecar_master_pid != 0 &&
current_pid != ddtrace_sidecar_master_pid);

if (is_child_process && ddtrace_sidecar_active_mode == DD_SIDECAR_CONNECTION_THREAD) {
// Clear inherited master listener state (child doesn't own it)
ddtrace_ffi_try("Failed clearing inherited listener state",
ddog_sidecar_clear_inherited_listener());

// Don't try to reconnect in thread mode after fork
// Let sidecar stay unavailable
LOG(WARN, "Child process after fork with thread mode: sidecar unavailable");
}
#endif
if (DDTRACE_G(agent_config_reader)) {
ddog_agent_remote_config_reader_drop(DDTRACE_G(agent_config_reader));
Expand Down
3 changes: 3 additions & 0 deletions ext/ddtrace_arginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,9 @@ static void register_ddtrace_symbols(int module_number)
REGISTER_LONG_CONSTANT("DDTrace\\DBM_PROPAGATION_DISABLED", DD_TRACE_DBM_PROPAGATION_DISABLED, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\DBM_PROPAGATION_SERVICE", DD_TRACE_DBM_PROPAGATION_SERVICE, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\DBM_PROPAGATION_FULL", DD_TRACE_DBM_PROPAGATION_FULL, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\SIDECAR_CONNECTION_MODE_AUTO", DD_TRACE_SIDECAR_CONNECTION_MODE_AUTO, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\SIDECAR_CONNECTION_MODE_SUBPROCESS", DD_TRACE_SIDECAR_CONNECTION_MODE_SUBPROCESS, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\SIDECAR_CONNECTION_MODE_THREAD", DD_TRACE_SIDECAR_CONNECTION_MODE_THREAD, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\Internal\\SPAN_FLAG_OPENTELEMETRY", DDTRACE_SPAN_FLAG_OPENTELEMETRY, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DDTrace\\Internal\\SPAN_FLAG_OPENTRACING", DDTRACE_SPAN_FLAG_OPENTRACING, CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DD_TRACE_VERSION", PHP_DDTRACE_VERSION, CONST_PERSISTENT);
Expand Down
9 changes: 9 additions & 0 deletions ext/handlers_pcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ static void dd_prefork() {

static void dd_handle_fork(zval *return_value) {
if (Z_LVAL_P(return_value) == 0) {
// CHILD PROCESS

// Warn if thread mode is active
if (ddtrace_sidecar_active_mode == DD_SIDECAR_CONNECTION_THREAD) {
LOG(WARN, "pcntl_fork() detected with thread-based sidecar connection. "
"Thread mode is incompatible with fork and may cause instability. "
"Consider using subprocess mode (DD_TRACE_SIDECAR_CONNECTION_MODE=subprocess).");
}

dd_internal_handle_fork();
} else {
#if JOIN_BGS_BEFORE_FORK
Expand Down
Loading
Loading