diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 655543465..965683027 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -139,3 +139,4 @@ The example currently supports the following commends: - `capture-multiple`: Captures a number of events. - `sleep`: Introduces a 10 second sleep. - `add-stacktrace`: Adds the current thread stacktrace to the captured event. +- `disable-backend`: Disables the build-configured crash-handler backend. diff --git a/examples/example.c b/examples/example.c index de086ea2e..0157b8071 100644 --- a/examples/example.c +++ b/examples/example.c @@ -65,6 +65,10 @@ main(int argc, char **argv) { sentry_options_t *options = sentry_options_new(); + if (has_arg(argc, argv, "disable-backend")) { + sentry_options_set_backend(options, NULL); + } + // this is an example. for real usage, make sure to set this explicitly to // an app specific cache location. sentry_options_set_database_path(options, ".sentry-native"); diff --git a/include/sentry.h b/include/sentry.h index 6552e42ff..c1b5ade4d 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -709,6 +709,20 @@ SENTRY_API void sentry_transport_free(sentry_transport_t *transport); SENTRY_API sentry_transport_t *sentry_new_function_transport( void (*func)(const sentry_envelope_t *envelope, void *data), void *data); +/** + * This represents an interface for user-defined backends. + * + * Backends are responsible to handle crashes. They are maintained at runtime + * via various life-cycle hooks from the sentry-core. + * + * At this point none of those interfaces are exposed in the API including + * creation and destruction. The main use-case of the backend in the API at this + * point is to disable it via `sentry_options_set_backend` at runtime before it + * is initialized. + */ +struct sentry_backend_s; +typedef struct sentry_backend_s sentry_backend_t; + /* -- Options APIs -- */ /** @@ -1050,6 +1064,16 @@ SENTRY_API void sentry_options_set_shutdown_timeout( */ SENTRY_API uint64_t sentry_options_get_shutdown_timeout(sentry_options_t *opts); +/** + * Sets a user-defined backend. + * + * Since creation and destruction of backends is not exposed in the API, this + * can only be used to set the backend to `NULL`, which disables the backend in + * the initialization. + */ +SENTRY_API void sentry_options_set_backend( + sentry_options_t *opts, sentry_backend_t *backend); + /* -- Global APIs -- */ /** diff --git a/src/sentry_options.c b/src/sentry_options.c index 43531118e..7588ad977 100644 --- a/src/sentry_options.c +++ b/src/sentry_options.c @@ -425,3 +425,10 @@ sentry_options_get_traces_sample_rate(sentry_options_t *opts) { return opts->traces_sample_rate; } + +void +sentry_options_set_backend(sentry_options_t *opts, sentry_backend_t *backend) +{ + sentry__backend_free(opts->backend); + opts->backend = backend; +} diff --git a/tests/test_integration_crashpad.py b/tests/test_integration_crashpad.py index 7eb0ca2c2..cd7363bed 100644 --- a/tests/test_integration_crashpad.py +++ b/tests/test_integration_crashpad.py @@ -135,3 +135,24 @@ def test_crashpad_dump_inflight(cmake, httpserver): # we trigger 10 normal events, and 1 crash assert len(httpserver.log) >= 11 + + +def test_disable_backend(cmake, httpserver): + tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"}) + + env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver)) + + with httpserver.wait(timeout=5, raise_assertions=False) as waiting: + child = run( + tmp_path, "sentry_example", ["disable-backend", "log", "crash"], env=env + ) + # we crash so process should return non-zero + assert child.returncode + + # crashpad is disabled, and we are only crashing, so we expect the wait to timeout + assert waiting.result is False + + run(tmp_path, "sentry_example", ["log", "no-setup"], check=True, env=env) + + # crashpad is disabled, and we are only crashing, so we expect no requests + assert len(httpserver.log) == 0