basic_logging_functionality (test_logs.c) is flaky. It has been observed to fail 4 times in the past week on Android emulator CI jobs (API 31 and API 35). Retrying usually makes it pass.
test_logs.c:70: Check 2 == 0... failed ← sentry_log_fatal() returned SENTRY_LOG_RETURN_FAILED
test_logs.c:75: Check 1 == 2... failed ← called_count was 1, expected 2
Details
The test fills the 5-slot batcher queue (SENTRY_BATCHER_QUEUE_LENGTH is 5 for unit tests), then calls sleep_ms(20) expecting the batcher thread to flush, before enqueuing a 6th log (fatal). The problem is that a timed sleep provides no ordering guarantee with respect to other threads — the batcher thread may not have been scheduled at all during that interval, or may still be mid-flush when the main thread resumes. Since sentry__batcher_enqueue retries only twice (ENQUEUE_MAX_RETRIES=2) with no backoff between attempts, all retries can exhaust instantly while the active buffer is still sealed. The fatal log is then dropped (SENTRY_LOG_RETURN_FAILED=2), and sentry_close() flushes only the original 5-item batch, yielding called_count=1 instead of 2.
Reproduced locally by pinning the test to a single CPU core under heavy system load (stress --cpu 8 --io 8 --vm 2 + taskset -c 0 nice -n 19): 16 failures out of 500 runs (3.2%).
basic_logging_functionality(test_logs.c) is flaky. It has been observed to fail 4 times in the past week on Android emulator CI jobs (API 31 and API 35). Retrying usually makes it pass.Details
The test fills the 5-slot batcher queue (
SENTRY_BATCHER_QUEUE_LENGTHis 5 for unit tests), then callssleep_ms(20)expecting the batcher thread to flush, before enqueuing a 6th log (fatal). The problem is that a timed sleep provides no ordering guarantee with respect to other threads — the batcher thread may not have been scheduled at all during that interval, or may still be mid-flush when the main thread resumes. Sincesentry__batcher_enqueueretries only twice (ENQUEUE_MAX_RETRIES=2) with no backoff between attempts, all retries can exhaust instantly while the active buffer is still sealed. The fatal log is then dropped (SENTRY_LOG_RETURN_FAILED=2), andsentry_close()flushes only the original 5-item batch, yieldingcalled_count=1instead of 2.Reproduced locally by pinning the test to a single CPU core under heavy system load (
stress --cpu 8 --io 8 --vm 2+taskset -c 0 nice -n 19): 16 failures out of 500 runs (3.2%).