From 604a3747d305861530c820675d71a5c9c0606cd4 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 22 Jun 2026 14:47:28 +0200 Subject: [PATCH 1/5] Propagate agent configured timeout to sidecar And make two RC tests more resilient to race conditions # Conflicts: # Cargo.lock --- Makefile | 2 +- ext/sidecar.c | 1 + tests/ext/remote_config/dynamic_config_multiconfig.phpt | 3 +++ tests/ext/remote_config/rc_fork_notify.phpt | 6 +++++- tests/ext/request-replayer/dd_trace_agent_env.phpt | 6 +----- tests/ext/telemetry/config.phpt | 1 + 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a48ff351cd9..0719eaeb1a3 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ TRACER_SOURCES_INI := -d datadog.trace.sources_path=$(TRACER_SOURCE_DIR) RUN_TESTS_IS_PARALLEL ?= $(shell test $(PHP_MAJOR_MINOR) -ge 74 && echo 1) # shuffle parallel tests to evenly distribute test load, avoiding a batch of 32 tests being request-replayer tests -RUN_TESTS_CMD := DD_SERVICE= DD_ENV= DD_TRACE_RETRY_INTERVAL=1 REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJECT_ROOT) USE_TRACKED_ALLOC=1 php -n -d 'memory_limit=-1' $(BUILD_DIR)/run-tests.php $(if $(QUIET_TESTS),,-g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP) $(if $(ASAN), --asan) --show-diff -n -p $(shell which php) -q $(if $(RUN_TESTS_IS_PARALLEL), --shuffle -j$(MAX_TEST_PARALLELISM)) +RUN_TESTS_CMD := DD_SERVICE= DD_ENV= DD_TRACE_RETRY_INTERVAL=1 DD_TRACE_AGENT_TIMEOUT=5000 REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJECT_ROOT) USE_TRACKED_ALLOC=1 php -n -d 'memory_limit=-1' $(BUILD_DIR)/run-tests.php $(if $(QUIET_TESTS),,-g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP) $(if $(ASAN), --asan) --show-diff -n -p $(shell which php) -q $(if $(RUN_TESTS_IS_PARALLEL), --shuffle -j$(MAX_TEST_PARALLELISM)) C_FILES = $(shell find components components-rs ext src/dogstatsd tracer zend_abstract_interface -name '*.c' -o -name '*.h' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) TEST_FILES = $(shell find tests/ext -name '*.php*' -o -name '*.inc' -o -name '*.json' -o -name '*.yaml' -o -name 'CONFLICTS' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) diff --git a/ext/sidecar.c b/ext/sidecar.c index 88df83479a9..224774d3a55 100644 --- a/ext/sidecar.c +++ b/ext/sidecar.c @@ -616,6 +616,7 @@ ddog_Endpoint *datadog_sidecar_agent_endpoint(void) { if (agent_endpoint) { dd_set_endpoint_test_token(agent_endpoint); + ddog_endpoint_set_timeout(agent_endpoint, get_global_DD_TRACE_AGENT_TIMEOUT()); } return agent_endpoint; diff --git a/tests/ext/remote_config/dynamic_config_multiconfig.phpt b/tests/ext/remote_config/dynamic_config_multiconfig.phpt index e63d09148c4..9da53ab6cac 100644 --- a/tests/ext/remote_config/dynamic_config_multiconfig.phpt +++ b/tests/ext/remote_config/dynamic_config_multiconfig.phpt @@ -32,6 +32,9 @@ $specific_path = put_dynamic_config_file([ ]); dd_trace_internal_fn("await_remote_config"); +if (ini_get("datadog.trace.sample_rate") == "0.3") { // possible race condition, just re-poll + dd_trace_internal_fn("await_remote_config"); +} // Specific config wins for sample_rate; org-level provides log_injection. print "After both configs:\n"; diff --git a/tests/ext/remote_config/rc_fork_notify.phpt b/tests/ext/remote_config/rc_fork_notify.phpt index d52dea75e13..25f72d6082c 100644 --- a/tests/ext/remote_config/rc_fork_notify.phpt +++ b/tests/ext/remote_config/rc_fork_notify.phpt @@ -15,7 +15,7 @@ DD_TRACE_AGENT_TEST_SESSION_TOKEN=remote-config/rc_fork_notify --FILE-- true]); } @@ -24,6 +24,10 @@ if (!ini_get("datadog.trace.enabled")) { dd_trace_internal_fn("await_remote_config"); } +if (!$child) { + pcntl_wait($status); +} + print ini_get("datadog.trace.enabled"); ?> diff --git a/tests/ext/request-replayer/dd_trace_agent_env.phpt b/tests/ext/request-replayer/dd_trace_agent_env.phpt index 50de644e70a..855da2ab544 100644 --- a/tests/ext/request-replayer/dd_trace_agent_env.phpt +++ b/tests/ext/request-replayer/dd_trace_agent_env.phpt @@ -37,11 +37,7 @@ $rr = new RequestReplayer(); $span = \DDTrace\start_span(); // make sure sidecar keeps up with us -$start = microtime(true); -\DDTrace\start_trace_span(); -\DDTrace\close_span(); -$rr->waitForDataAndReplay(); -usleep(floor(microtime(true) - $start) * 100000); +dd_trace_internal_fn('await_agent_info'); \DDTrace\close_span(); var_dump($span->env); diff --git a/tests/ext/telemetry/config.phpt b/tests/ext/telemetry/config.phpt index 007f2722aeb..915e22a2cec 100644 --- a/tests/ext/telemetry/config.phpt +++ b/tests/ext/telemetry/config.phpt @@ -19,6 +19,7 @@ DD_TRACE_AUTOFINISH_SPANS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_AGENT_HOST= DD_AUTOLOAD_NO_COMPILE= +DD_TRACE_AGENT_TIMEOUT= DD_TRACE_RETRY_INTERVAL= DD_TRACE_GIT_METADATA_ENABLED=0 DD_TRACE_IGNORE_AGENT_SAMPLING_RATES=1 From 37b03d3716591f48441ea2fe44a5a33d79e79a51 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 30 Jun 2026 19:39:17 +0200 Subject: [PATCH 2/5] Set low timeouts in tests accessing invalid urls --- Makefile | 10 +++++----- tests/ext/appsec/sca_flag_is_sent_01.phpt | 2 ++ tests/ext/appsec/sca_flag_is_sent_02.phpt | 2 ++ tests/ext/appsec/sca_flag_is_sent_03.phpt | 2 ++ tests/ext/appsec/sca_flag_is_sent_04.phpt | 2 ++ tests/ext/appsec/sca_flag_is_sent_05.phpt | 2 ++ .../background_sender_ipv6_support.phpt | 2 ++ .../cli_shutdown_no_hang_unreachable_agent.phpt | 5 +++-- .../sidecar_handles_invalid_agent_url.phpt | 2 ++ tests/ext/library_config/fleet_config.phpt | 2 ++ tests/ext/library_config/local_config.phpt | 2 ++ tests/ext/startup_logging_diagnostics.phpt | 2 ++ tests/ext/telemetry/broken_pipe.phpt | 2 ++ tests/ext/telemetry/composer.phpt | 2 ++ tests/ext/telemetry/config.phpt | 6 +++--- tests/ext/telemetry/disabled.phpt | 2 ++ tests/ext/telemetry/integration.phpt | 2 ++ tests/ext/telemetry/integration_filesystem_01.phpt | 2 ++ tests/ext/telemetry/integration_filesystem_02.phpt | 2 ++ tests/ext/telemetry/integration_filesystem_03.phpt | 2 ++ tests/ext/telemetry/integration_filesystem_04.phpt | 2 ++ tests/ext/telemetry/integration_runtime_error.phpt | 2 ++ tests/ext/telemetry/metrics_logs_created.phpt | 2 ++ tests/ext/telemetry/metrics_spans_created.phpt | 2 ++ tests/ext/telemetry/simple.phpt | 2 ++ tests/ext/telemetry/telemetry_process_tags.phpt | 2 ++ 26 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 0719eaeb1a3..0c2af01d47d 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ TRACER_SOURCES_INI := -d datadog.trace.sources_path=$(TRACER_SOURCE_DIR) RUN_TESTS_IS_PARALLEL ?= $(shell test $(PHP_MAJOR_MINOR) -ge 74 && echo 1) # shuffle parallel tests to evenly distribute test load, avoiding a batch of 32 tests being request-replayer tests -RUN_TESTS_CMD := DD_SERVICE= DD_ENV= DD_TRACE_RETRY_INTERVAL=1 DD_TRACE_AGENT_TIMEOUT=5000 REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJECT_ROOT) USE_TRACKED_ALLOC=1 php -n -d 'memory_limit=-1' $(BUILD_DIR)/run-tests.php $(if $(QUIET_TESTS),,-g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP) $(if $(ASAN), --asan) --show-diff -n -p $(shell which php) -q $(if $(RUN_TESTS_IS_PARALLEL), --shuffle -j$(MAX_TEST_PARALLELISM)) +RUN_TESTS_CMD := DD_SERVICE= DD_ENV= REPORT_EXIT_STATUS=1 TEST_PHP_SRCDIR=$(PROJECT_ROOT) USE_TRACKED_ALLOC=1 php -n -d 'memory_limit=-1' $(BUILD_DIR)/run-tests.php $(if $(QUIET_TESTS),,-g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP) $(if $(ASAN), --asan) --show-diff -n -p $(shell which php) -q $(if $(RUN_TESTS_IS_PARALLEL), --shuffle -j$(MAX_TEST_PARALLELISM)) C_FILES = $(shell find components components-rs ext src/dogstatsd tracer zend_abstract_interface -name '*.c' -o -name '*.h' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) TEST_FILES = $(shell find tests/ext -name '*.php*' -o -name '*.inc' -o -name '*.json' -o -name '*.yaml' -o -name 'CONFLICTS' | awk '{ printf "$(BUILD_DIR)/%s\n", $$1 }' ) @@ -165,10 +165,10 @@ install_appsec: install_all: install install_ini run_tests: $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) $(TESTS) + $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) $(TESTS) test_c: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) + $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) test_c_coverage: dist_clean DD_TRACE_DOCKER_DEBUG=1 EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage" $(MAKE) test_c || exit 0 @@ -207,11 +207,11 @@ test_extension_ci: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run- set -xe; \ export PATH="$(PROJECT_ROOT)/tests/ext/valgrind:$$PATH"; \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/normal-extension-test.xml; \ - $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ + $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/valgrind-extension-test.xml; \ export TEST_PHP_OUTPUT=$(JUNIT_RESULTS_DIR)/valgrind-run-tests.out; \ - DD_SPAWN_WORKER_STABLE_TRAMPOLINE=1 $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) -d extension=$(SO_FILE) -m -s $$TEST_PHP_OUTPUT $(BUILD_DIR)/$(TESTS) && ! grep -e '^LEAKED TEST SUMMARY' $$TEST_PHP_OUTPUT; \ + DD_SPAWN_WORKER_STABLE_TRAMPOLINE=1 $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=5000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) -m -s $$TEST_PHP_OUTPUT $(BUILD_DIR)/$(TESTS) && ! grep -e '^LEAKED TEST SUMMARY' $$TEST_PHP_OUTPUT; \ ) build_tea: TEA_BUILD_TESTS=ON diff --git a/tests/ext/appsec/sca_flag_is_sent_01.phpt b/tests/ext/appsec/sca_flag_is_sent_01.phpt index bc8a4a35d84..dec47246c15 100644 --- a/tests/ext/appsec/sca_flag_is_sent_01.phpt +++ b/tests/ext/appsec/sca_flag_is_sent_01.phpt @@ -12,6 +12,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/sca_flag_is_sent_01-telemetry.out" --FILE_EXTERNAL-- diff --git a/tests/ext/appsec/sca_flag_is_sent_02.phpt b/tests/ext/appsec/sca_flag_is_sent_02.phpt index d400ff4aa1b..0bf28f1d14c 100644 --- a/tests/ext/appsec/sca_flag_is_sent_02.phpt +++ b/tests/ext/appsec/sca_flag_is_sent_02.phpt @@ -13,6 +13,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_APPSEC_SCA_ENABLED=true +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/sca_flag_is_sent_02-telemetry.out" --FILE_EXTERNAL-- diff --git a/tests/ext/appsec/sca_flag_is_sent_03.phpt b/tests/ext/appsec/sca_flag_is_sent_03.phpt index a989d3e7388..11164a0670c 100644 --- a/tests/ext/appsec/sca_flag_is_sent_03.phpt +++ b/tests/ext/appsec/sca_flag_is_sent_03.phpt @@ -13,6 +13,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_APPSEC_SCA_ENABLED=false +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/sca_flag_is_sent_03-telemetry.out" --FILE_EXTERNAL-- diff --git a/tests/ext/appsec/sca_flag_is_sent_04.phpt b/tests/ext/appsec/sca_flag_is_sent_04.phpt index e0ce9d59395..18270a8a63b 100644 --- a/tests/ext/appsec/sca_flag_is_sent_04.phpt +++ b/tests/ext/appsec/sca_flag_is_sent_04.phpt @@ -12,6 +12,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/sca_flag_is_sent_04-telemetry.out" datadog.appsec.sca_enabled=1 diff --git a/tests/ext/appsec/sca_flag_is_sent_05.phpt b/tests/ext/appsec/sca_flag_is_sent_05.phpt index 73f06a8ce8f..3f33dceffe8 100644 --- a/tests/ext/appsec/sca_flag_is_sent_05.phpt +++ b/tests/ext/appsec/sca_flag_is_sent_05.phpt @@ -12,6 +12,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/sca_flag_is_sent_05-telemetry.out" datadog.appsec.sca_enabled=0 diff --git a/tests/ext/background-sender/background_sender_ipv6_support.phpt b/tests/ext/background-sender/background_sender_ipv6_support.phpt index 06405102053..df66ad29d2f 100644 --- a/tests/ext/background-sender/background_sender_ipv6_support.phpt +++ b/tests/ext/background-sender/background_sender_ipv6_support.phpt @@ -9,6 +9,8 @@ include_once __DIR__ . '/../startup_logging.inc'; $logs = dd_get_startup_logs([], [ 'DD_AGENT_HOST' => '::1', 'DD_TRACE_DEBUG' => 1, + 'DD_TRACE_AGENT_TIMEOUT' => 200, + 'DD_TRACE_RETRY_INTERVAL' => 1, ]); dd_dump_startup_logs($logs, [ diff --git a/tests/ext/background-sender/cli_shutdown_no_hang_unreachable_agent.phpt b/tests/ext/background-sender/cli_shutdown_no_hang_unreachable_agent.phpt index 79361ae474d..759b6d1f5ff 100644 --- a/tests/ext/background-sender/cli_shutdown_no_hang_unreachable_agent.phpt +++ b/tests/ext/background-sender/cli_shutdown_no_hang_unreachable_agent.phpt @@ -18,8 +18,9 @@ DD_AGENT_HOST=192.0.2.1 DD_TRACE_AGENT_PORT=18126 DD_TRACE_SIDECAR_TRACE_SENDER=0 DD_TRACE_SHUTDOWN_TIMEOUT=2000 -DD_TRACE_AGENT_TIMEOUT=500 -DD_TRACE_AGENT_CONNECT_TIMEOUT=500 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_AGENT_CONNECT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 DD_TRACE_AGENT_RETRIES=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=0 DD_REMOTE_CONFIG_ENABLED=0 diff --git a/tests/ext/background-sender/sidecar_handles_invalid_agent_url.phpt b/tests/ext/background-sender/sidecar_handles_invalid_agent_url.phpt index ffeddf8c2a4..7f5a15f463a 100644 --- a/tests/ext/background-sender/sidecar_handles_invalid_agent_url.phpt +++ b/tests/ext/background-sender/sidecar_handles_invalid_agent_url.phpt @@ -7,6 +7,8 @@ The sidecar properly handles invalid agent urls DD_TRACE_AGENT_URL=/invalid DD_TRACE_SIDECAR_TRACE_SENDER=1 DD_CRASHTRACKING_ENABLED=0 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --FILE-- '1', + 'DD_TRACE_AGENT_TIMEOUT' => 200, + 'DD_TRACE_RETRY_INTERVAL' => 1, 'DD_AGENT_HOST' => 'invalid_host', 'DD_SERVICE' => 'foo_service', 'DD_TAGS' => 'foo:tag', diff --git a/tests/ext/telemetry/broken_pipe.phpt b/tests/ext/telemetry/broken_pipe.phpt index d4686176cf6..9bd666c7b43 100644 --- a/tests/ext/telemetry/broken_pipe.phpt +++ b/tests/ext/telemetry/broken_pipe.phpt @@ -11,6 +11,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_TRACE_LOG_LEVEL=info,startup=off +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/broken_pipe-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/composer.phpt b/tests/ext/telemetry/composer.phpt index 700c95dc282..b7395e6bbf1 100644 --- a/tests/ext/telemetry/composer.phpt +++ b/tests/ext/telemetry/composer.phpt @@ -10,6 +10,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/composer-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/config.phpt b/tests/ext/telemetry/config.phpt index 915e22a2cec..f17abcbf7b8 100644 --- a/tests/ext/telemetry/config.phpt +++ b/tests/ext/telemetry/config.phpt @@ -19,8 +19,8 @@ DD_TRACE_AUTOFINISH_SPANS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_AGENT_HOST= DD_AUTOLOAD_NO_COMPILE= -DD_TRACE_AGENT_TIMEOUT= -DD_TRACE_RETRY_INTERVAL= +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 DD_TRACE_GIT_METADATA_ENABLED=0 DD_TRACE_IGNORE_AGENT_SAMPLING_RATES=1 DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=0 @@ -50,7 +50,7 @@ for ($i = 0; $i < 300; ++$i) { if ($json["request_type"] == "app-client-configuration-change") { $cfg = $json["payload"]["configuration"]; print_r(array_values(array_filter($cfg, function ($c) { - return $c["origin"] == "env_var" && $c["name"] != "DD_TRACE_SOURCES_PATH" && $c["name"] != "DD_TRACE_SIDECAR_TRACE_SENDER"; + return $c["origin"] == "env_var" && $c["name"] != "DD_TRACE_SOURCES_PATH" && $c["name"] != "DD_TRACE_SIDECAR_TRACE_SENDER" && $c["name"] != "DD_TRACE_AGENT_TIMEOUT" && $c["name"] != "DD_TRACE_RETRY_INTERVAL"; }))); var_dump(count(array_filter($cfg, function ($c) { return $c["origin"] == "default"; diff --git a/tests/ext/telemetry/disabled.phpt b/tests/ext/telemetry/disabled.phpt index 757758a22cd..e6ba0a1c769 100644 --- a/tests/ext/telemetry/disabled.phpt +++ b/tests/ext/telemetry/disabled.phpt @@ -8,6 +8,8 @@ if (PHP_OS === "WINNT" && PHP_VERSION_ID < 70400) die("skip: Windows on PHP 7.2 --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=0 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/disabled-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/integration.phpt b/tests/ext/telemetry/integration.phpt index cde1e21ad97..2474961f006 100644 --- a/tests/ext/telemetry/integration.phpt +++ b/tests/ext/telemetry/integration.phpt @@ -11,6 +11,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/integration_filesystem_01.phpt b/tests/ext/telemetry/integration_filesystem_01.phpt index 3591fec5424..81a55e80a2e 100644 --- a/tests/ext/telemetry/integration_filesystem_01.phpt +++ b/tests/ext/telemetry/integration_filesystem_01.phpt @@ -12,6 +12,8 @@ DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_APPSEC_RASP_ENABLED=0 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-telemetry-01.out" --FILE-- diff --git a/tests/ext/telemetry/integration_filesystem_02.phpt b/tests/ext/telemetry/integration_filesystem_02.phpt index 685626318db..19a04edd4cb 100644 --- a/tests/ext/telemetry/integration_filesystem_02.phpt +++ b/tests/ext/telemetry/integration_filesystem_02.phpt @@ -12,6 +12,8 @@ DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_LOGS_INJECTION=false +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-telemetry-02.out" --FILE-- diff --git a/tests/ext/telemetry/integration_filesystem_03.phpt b/tests/ext/telemetry/integration_filesystem_03.phpt index 61275011d1a..75b5ab03b1d 100644 --- a/tests/ext/telemetry/integration_filesystem_03.phpt +++ b/tests/ext/telemetry/integration_filesystem_03.phpt @@ -11,6 +11,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-telemetry-03.out" --FILE-- diff --git a/tests/ext/telemetry/integration_filesystem_04.phpt b/tests/ext/telemetry/integration_filesystem_04.phpt index 16fe5991cfb..b78a90a050d 100644 --- a/tests/ext/telemetry/integration_filesystem_04.phpt +++ b/tests/ext/telemetry/integration_filesystem_04.phpt @@ -12,6 +12,8 @@ DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_TRACE_FILESYSTEM_ENABLED=0 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-telemetry-04.out" --FILE-- diff --git a/tests/ext/telemetry/integration_runtime_error.phpt b/tests/ext/telemetry/integration_runtime_error.phpt index 896e251df62..aebe831f8c9 100644 --- a/tests/ext/telemetry/integration_runtime_error.phpt +++ b/tests/ext/telemetry/integration_runtime_error.phpt @@ -12,6 +12,8 @@ DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_TELEMETRY_LOG_COLLECTION_ENABLED=1 DD_TRACE_LOG_LEVEL=warn +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/integration-runtime-error-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/metrics_logs_created.phpt b/tests/ext/telemetry/metrics_logs_created.phpt index 9769ca47128..1ddc719c44f 100644 --- a/tests/ext/telemetry/metrics_logs_created.phpt +++ b/tests/ext/telemetry/metrics_logs_created.phpt @@ -11,6 +11,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_TRACE_LOG_LEVEL=warn +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/metrics-logs-created-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/metrics_spans_created.phpt b/tests/ext/telemetry/metrics_spans_created.phpt index c63ed2648dc..fa8ffaabc7d 100644 --- a/tests/ext/telemetry/metrics_spans_created.phpt +++ b/tests/ext/telemetry/metrics_spans_created.phpt @@ -11,6 +11,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/metrics-spans_created-telemetry.out" zend.assertions=1 diff --git a/tests/ext/telemetry/simple.phpt b/tests/ext/telemetry/simple.phpt index a11fc653ebd..63ea017185f 100644 --- a/tests/ext/telemetry/simple.phpt +++ b/tests/ext/telemetry/simple.phpt @@ -10,6 +10,8 @@ require __DIR__ . '/../includes/clear_skipif_telemetry.inc' --ENV-- DD_TRACE_GENERATE_ROOT_SPAN=0 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/simple-telemetry.out" --FILE-- diff --git a/tests/ext/telemetry/telemetry_process_tags.phpt b/tests/ext/telemetry/telemetry_process_tags.phpt index a92bbd44221..85b5a35ed73 100644 --- a/tests/ext/telemetry/telemetry_process_tags.phpt +++ b/tests/ext/telemetry/telemetry_process_tags.phpt @@ -12,6 +12,8 @@ DD_TRACE_GENERATE_ROOT_SPAN=0 _DD_LOAD_TEST_INTEGRATIONS=1 DD_INSTRUMENTATION_TELEMETRY_ENABLED=1 DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED=1 +DD_TRACE_AGENT_TIMEOUT=200 +DD_TRACE_RETRY_INTERVAL=1 --INI-- datadog.trace.agent_url="file://{PWD}/process-tags-telemetry.out" --FILE-- From 01e346d98f1bec13e05d88ab6d7c34f197703884 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 30 Jun 2026 20:21:34 +0200 Subject: [PATCH 3/5] Increase default timeout a bit --- Makefile | 6 +++--- ext/configuration.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0c2af01d47d..267db6a4ddd 100644 --- a/Makefile +++ b/Makefile @@ -165,10 +165,10 @@ install_appsec: install_all: install install_ini run_tests: $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) $(TESTS) + $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) $(TESTS) test_c: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) + $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) test_c_coverage: dist_clean DD_TRACE_DOCKER_DEBUG=1 EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage" $(MAKE) test_c || exit 0 @@ -207,7 +207,7 @@ test_extension_ci: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run- set -xe; \ export PATH="$(PROJECT_ROOT)/tests/ext/valgrind:$$PATH"; \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/normal-extension-test.xml; \ - $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=1000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ + $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/valgrind-extension-test.xml; \ export TEST_PHP_OUTPUT=$(JUNIT_RESULTS_DIR)/valgrind-run-tests.out; \ diff --git a/ext/configuration.h b/ext/configuration.h index e68326c8912..d047115c7c9 100644 --- a/ext/configuration.h +++ b/ext/configuration.h @@ -28,7 +28,7 @@ enum datadog_sidecar_connection_mode { * A user hit an issue with the userland time of 100. */ #define DD_TRACE_AGENT_CONNECT_TIMEOUT_VAL 100 -#define DD_TRACE_AGENT_TIMEOUT_VAL 500 +#define DD_TRACE_AGENT_TIMEOUT_VAL 1000 #define DD_TRACE_AGENT_FLUSH_INTERVAL_VAL 1001 #define DD_CFG_STR(str) #str From 6dcfe622c2fd13f604f035f6e1046948a7f0d6cd Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Fri, 3 Jul 2026 18:42:44 +0200 Subject: [PATCH 4/5] Increase default timeout a bit more, for sidecar only --- Makefile | 6 +++--- ext/configuration.h | 2 +- metadata/supported-configurations.json | 4 ++-- .../background-sender/agent_headers_unix_domain_socket.phpt | 3 +++ .../background-sender/default_unix_domain_socket_agent.phpt | 3 +++ tracer/coms.c | 4 +++- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 267db6a4ddd..aa1ba9dad6f 100644 --- a/Makefile +++ b/Makefile @@ -165,10 +165,10 @@ install_appsec: install_all: install install_ini run_tests: $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) $(TESTS) + $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) $(TESTS) test_c: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run-tests.php - $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) + $(if $(ASAN), USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 LSAN_OPTIONS=fast_unwind_on_malloc=0$${LSAN_OPTIONS:+$(,)$${LSAN_OPTIONS}}) $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(subst $(BUILD_DIR_NAME)/,,$(TESTS)) test_c_coverage: dist_clean DD_TRACE_DOCKER_DEBUG=1 EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage" $(MAKE) test_c || exit 0 @@ -207,7 +207,7 @@ test_extension_ci: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES) $(BUILD_DIR)/run- set -xe; \ export PATH="$(PROJECT_ROOT)/tests/ext/valgrind:$$PATH"; \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/normal-extension-test.xml; \ - $(ALL_TEST_ENV_OVERRIDE) DD_TRACE_AGENT_TIMEOUT=2000 $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ + $(ALL_TEST_ENV_OVERRIDE) $(RUN_TESTS_CMD) -d extension=$(SO_FILE) $(BUILD_DIR)/$(TESTS); \ \ export TEST_PHP_JUNIT=$(JUNIT_RESULTS_DIR)/valgrind-extension-test.xml; \ export TEST_PHP_OUTPUT=$(JUNIT_RESULTS_DIR)/valgrind-run-tests.out; \ diff --git a/ext/configuration.h b/ext/configuration.h index d047115c7c9..4481d7fd8bb 100644 --- a/ext/configuration.h +++ b/ext/configuration.h @@ -28,7 +28,7 @@ enum datadog_sidecar_connection_mode { * A user hit an issue with the userland time of 100. */ #define DD_TRACE_AGENT_CONNECT_TIMEOUT_VAL 100 -#define DD_TRACE_AGENT_TIMEOUT_VAL 1000 +#define DD_TRACE_AGENT_TIMEOUT_VAL 3000 #define DD_TRACE_AGENT_FLUSH_INTERVAL_VAL 1001 #define DD_CFG_STR(str) #str diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 361057fad8f..a297e5c65ab 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -786,9 +786,9 @@ ], "DD_TRACE_AGENT_TIMEOUT": [ { - "implementation": "B", + "implementation": "C", "type": "int", - "default": "500" + "default": "3000" } ], "DD_TRACE_AGENT_URL": [ diff --git a/tests/ext/background-sender/agent_headers_unix_domain_socket.phpt b/tests/ext/background-sender/agent_headers_unix_domain_socket.phpt index 1293e47be72..040b4d15b2f 100644 --- a/tests/ext/background-sender/agent_headers_unix_domain_socket.phpt +++ b/tests/ext/background-sender/agent_headers_unix_domain_socket.phpt @@ -25,6 +25,9 @@ $proxy = RequestReplayer::launchUnixProxy(str_replace("unix://", "", getenv("DD_ \DDTrace\start_span(); \DDTrace\close_span(); +// ensure the response also is received by the sender first, to avoid retries holding up other tests +dd_trace_internal_fn("synchronous_flush"); + echo PHP_EOL; $headers = $rr->replayHeaders([ 'content-type', diff --git a/tests/ext/background-sender/default_unix_domain_socket_agent.phpt b/tests/ext/background-sender/default_unix_domain_socket_agent.phpt index 8b08b338e03..e5feeb9b91a 100644 --- a/tests/ext/background-sender/default_unix_domain_socket_agent.phpt +++ b/tests/ext/background-sender/default_unix_domain_socket_agent.phpt @@ -6,6 +6,9 @@ If an agent unix domain socket exists it will try to connect to it --ENV-- +DD_TRACE_GENERATE_ROOT_SPAN=0 +DD_INSTRUMENTATION_TELEMETRY_ENABLED=0 +DD_REMOTE_CONFIG_ENABLED=0 DD_AGENT_HOST= --FILE-- = b ? a : b; } +// Shorter time for in-process timeout void ddtrace_curl_set_timeout(CURL *curl) { - long timeout = dd_max_long(get_global_DD_TRACE_BGS_TIMEOUT(), get_global_DD_TRACE_AGENT_TIMEOUT()); + long agent_timeout = zai_config_memoized_entries[DATADOG_CONFIG_DD_TRACE_AGENT_TIMEOUT].name_index == ZAI_CONFIG_ORIGIN_DEFAULT ? 500 : get_global_DD_TRACE_AGENT_TIMEOUT(); + long timeout = dd_max_long(get_global_DD_TRACE_BGS_TIMEOUT(), agent_timeout); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout); } From 21028080e203901313ccc42398a5bedffda3d57b Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sat, 25 Jul 2026 16:45:15 +0200 Subject: [PATCH 5/5] Try more elaborate unix socket proxy --- tests/ext/includes/request_replayer.inc | 59 +++---- tests/ext/includes/unix_socket_proxy.php | 186 +++++++++++++++++++++++ 2 files changed, 216 insertions(+), 29 deletions(-) create mode 100644 tests/ext/includes/unix_socket_proxy.php diff --git a/tests/ext/includes/request_replayer.inc b/tests/ext/includes/request_replayer.inc index 764bb9d98de..a4567e3ef69 100644 --- a/tests/ext/includes/request_replayer.inc +++ b/tests/ext/includes/request_replayer.inc @@ -6,12 +6,11 @@ ini_set("datadog.trace.httpstream_enabled", 0); class ProxyContainer { public $proc; - public function __construct($proc) { - $this->proc = $proc; - } + private $pipes; - public function __destruct() { - proc_terminate($this->proc, 9); + public function __construct($proc, array $pipes) { + $this->proc = $proc; + $this->pipes = $pipes; } } @@ -203,32 +202,34 @@ class RequestReplayer ])); } - public static function launchUnixProxy($socketPath) { + /** + * Serves $socketPath and forwards everything to the request-replayer, so + * that the tracer's unix socket agent transport can be tested. + * + * Launches unix_socket_proxy.php. + */ + public static function launchUnixProxy($socketPath, $upstream = "request-replayer:80") { @unlink($socketPath); - $code = str_replace("\n", "", ' -ignore_user_abort(true); /* prevent bailout... */ -$server = stream_socket_server("unix://' . $socketPath . '"); -print "1\n"; /* ready marker */ -while ($client = stream_socket_accept($server, 5)) { - file_put_contents("/tmp/unix-proxy-' . basename($socketPath) . '", "connected\n", FILE_APPEND); - $replayer = stream_socket_client("request-replayer:80"); - $all = $read = [$client, $replayer]; - foreach ($read as $fp) stream_set_blocking($fp, false); - while (stream_select($read, $w, $e, null)) { - $data = fread($fp = reset($read), 4096); - if ($data == "") { - file_put_contents("/tmp/unix-proxy-' . basename($socketPath) . '", "end\n", FILE_APPEND); - break; + + // -n: run without any php.ini, so the proxy does not itself load + // ddtrace and send agent requests into the socket it is serving. + $cmd = PHP_BINARY . " -n " . escapeshellarg(__DIR__ . "/unix_socket_proxy.php") + . " " . escapeshellarg($socketPath) . " " . escapeshellarg($upstream); + // stdin is a pipe on purpose: the proxy exits once it hits EOF there, + // which happens as soon as this process is gone. That avoids both a + // leaked proxy and the previous inactivity timeout, which killed the + // proxy while a test was still running. + $proc = proc_open($cmd, [["pipe", "r"], ["pipe", "w"], STDERR], $pipes); + if (!is_resource($proc)) { + throw new Exception("failed to launch unix proxy for $socketPath"); + } + + if (fread($pipes[1], 1) !== "1") { // ready marker + fclose($pipes[0]); + proc_close($proc); + throw new Exception("unix proxy for $socketPath failed to start"); } - file_put_contents("/tmp/unix-proxy-' . basename($socketPath) . '", "$data\n", FILE_APPEND); - fwrite($fp == $replayer ? $client : $replayer, $data); - $read = $all; - } -} -'); - $proc = proc_open(PHP_BINARY . " -r '$code'", [STDIN, ["pipe", "w"], STDERR], $pipes); - fread($pipes[1], 1); // ready - return new ProxyContainer($proc); + return new ProxyContainer($proc, [$pipes[0]]); } } diff --git a/tests/ext/includes/unix_socket_proxy.php b/tests/ext/includes/unix_socket_proxy.php new file mode 100644 index 00000000000..e333e5affdd --- /dev/null +++ b/tests/ext/includes/unix_socket_proxy.php @@ -0,0 +1,186 @@ + [] [] + * + * Parent protocol: + * - prints "1\n" on stdout once the socket accepts connections + * - exits once stdin hits EOF, i.e. once the test process launching it is gone + */ + +const CHUNK_SIZE = 65536; +/* Stop reading from a socket while this much data is still queued for its peer. */ +const MAX_BUFFERED = 4 * CHUNK_SIZE; + +if (!isset($argv[1])) { + fwrite(STDERR, "usage: unix_socket_proxy.php [] []\n"); + exit(1); +} + +$socketPath = $argv[1]; +$upstreamAddr = isset($argv[2]) ? $argv[2] : 'request-replayer:80'; +$logFile = isset($argv[3]) ? $argv[3] : '/tmp/unix-proxy-' . basename($socketPath); + +ignore_user_abort(true); + +@unlink($socketPath); +$server = @stream_socket_server('unix://' . $socketPath, $errno, $errstr); +if (!$server) { + fwrite(STDERR, "unix_socket_proxy: cannot listen on $socketPath: $errstr ($errno)\n"); + exit(1); +} +stream_set_blocking($server, false); + +echo "1\n"; /* ready marker, awaited by launchUnixProxy() */ +flush(); + +/* id => ['client' => resource, 'upstream' => resource, 'out' => [side => string], ...] */ +$conns = []; +/* (int) resource => [id, side] */ +$owner = []; +$nextId = 0; + +function other_side($side) +{ + return $side === 'client' ? 'upstream' : 'client'; +} + +/** + * Tests grep the proxied bytes out of this file, so keep the format as is: + * one chunk per write, each starting on a fresh line. + */ +function proxy_log($data) +{ + global $logFile; + file_put_contents($logFile, $data . "\n", FILE_APPEND); +} + +function close_pair($id) +{ + global $conns, $owner; + foreach (['client', 'upstream'] as $side) { + $stream = $conns[$id][$side]; + unset($owner[(int) $stream]); + @fclose($stream); + } + unset($conns[$id]); +} + +function accept_pending() +{ + global $server, $upstreamAddr, $conns, $owner, $nextId; + + while (($client = @stream_socket_accept($server, 0)) !== false) { + $upstream = @stream_socket_client('tcp://' . $upstreamAddr, $errno, $errstr, 5); + if (!$upstream) { + proxy_log("upstream connect to $upstreamAddr failed: $errstr ($errno)"); + fclose($client); + continue; + } + stream_set_blocking($client, false); + stream_set_blocking($upstream, false); + + $id = $nextId++; + $conns[$id] = [ + 'client' => $client, + 'upstream' => $upstream, + 'out' => ['client' => '', 'upstream' => ''], + 'eof' => ['client' => false, 'upstream' => false], + 'shutdown' => ['client' => false, 'upstream' => false], + ]; + $owner[(int) $client] = [$id, 'client']; + $owner[(int) $upstream] = [$id, 'upstream']; + proxy_log('connected'); + } +} + +while (true) { + $read = [STDIN, $server]; + $write = []; + foreach ($conns as $id => $conn) { + foreach (['client', 'upstream'] as $side) { + if (!$conn['eof'][$side] && strlen($conn['out'][other_side($side)]) < MAX_BUFFERED) { + $read[] = $conn[$side]; + } + if ($conn['out'][$side] !== '') { + $write[] = $conn[$side]; + } + } + } + + $except = null; + if (@stream_select($read, $write, $except, null) === false) { + break; /* interrupted by a signal */ + } + + foreach ($read as $stream) { + if ($stream === STDIN) { + /* The test process that launched us is gone. */ + @unlink($socketPath); + exit(0); + } + + if ($stream === $server) { + accept_pending(); + continue; + } + + if (!isset($owner[(int) $stream])) { + continue; /* closed while handling an earlier stream in this batch */ + } + list($id, $side) = $owner[(int) $stream]; + + $data = @fread($stream, CHUNK_SIZE); + if ($data === false || $data === '') { + $conns[$id]['eof'][$side] = true; + proxy_log('end'); + } else { + proxy_log($data); + $conns[$id]['out'][other_side($side)] .= $data; + } + } + + foreach ($conns as $id => $conn) { + foreach (['client', 'upstream'] as $side) { + if ($conns[$id]['out'][$side] === '') { + continue; + } + /* Sockets are non-blocking: a short write is normal, keep the rest queued. */ + $written = @fwrite($conns[$id][$side], $conns[$id]['out'][$side]); + if ($written === false) { + $conns[$id]['out'][$side] = ''; + $conns[$id]['eof'][$side] = true; + continue; + } + $conns[$id]['out'][$side] = substr($conns[$id]['out'][$side], $written); + } + } + + foreach ($conns as $id => $conn) { + /* + * Forward each half-close once everything read before it has been + * handed over. Responses delimited by connection close depend on this. + */ + foreach (['client', 'upstream'] as $side) { + $peer = other_side($side); + if ($conns[$id]['eof'][$side] + && $conns[$id]['out'][$peer] === '' + && !$conns[$id]['shutdown'][$peer] + ) { + @stream_socket_shutdown($conns[$id][$peer], STREAM_SHUT_WR); + $conns[$id]['shutdown'][$peer] = true; + } + } + + if ($conns[$id]['eof']['client'] && $conns[$id]['eof']['upstream'] + && $conns[$id]['out']['client'] === '' && $conns[$id]['out']['upstream'] === '' + ) { + close_pair($id); + } + } +}