Skip to content

ASIO backend panics with "attempt to add with overflow" in TimeBase::to_stream_instant after a few minutes (debug builds), small buffer size #1370

Description

@ZackPedretti

Summary

Using the ASIO host with a small fixed buffer size (16 frames), the ASIO
input/output stream panics after a few minutes of continuous playback with
attempt to add with overflow inside TimeBase::to_stream_instant
(src/host/asio/stream.rs:44). Only reproduces in debug builds (overflow
checks enabled); release builds presumably wrap silently instead.

Environment

  • cpal: 0.18.2
  • OS: Windows 11 Professional (10.0.26200 Build 26200)
  • Interface: Focusrite USB ASIO (Focusrite Scarlett 2i2 3rd Gen)
  • Rust toolchain: (rustc 1.98.1 (48a229cea 2026-09-01))
  • Profile: debug (cargo run)

Minimal repro, using a Focusrite interface over ASIO with a 16-frame fixed
buffer, 44.1kHz, 2ch, i32, simply copying input channel 0 to both output
channels via a ring buffer:

use std::time::Duration;
use anyhow::anyhow;
use cpal::{BufferSize, StreamConfig};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use ringbuf::consumer::Consumer;
use ringbuf::HeapRb;
use ringbuf::producer::Producer;
use ringbuf::traits::Split;

fn main() -> anyhow::Result<()> {
    let host = cpal::host_from_id(cpal::HostId::Asio)?;
    let devices = host.devices()?;

    let focusrite = devices
        .filter_map(|device| {
            let description = device.description().ok()?;

            if description.to_string().contains("Focusrite USB ASIO") {
                Some(device)
            } else {
                None
            }
        })
        .next()
        .ok_or_else(|| anyhow!("Focusrite USB ASIO not found"))?;

    println!("Using device: {}", focusrite.description()?);

    let config = StreamConfig {
        channels: 2,
        sample_rate: 44_100,
        buffer_size: BufferSize::Fixed(16),
    };

    println!("Config: {config:?}");

    let ring = HeapRb::<i32>::new(16_384);

    let (mut producer, mut consumer) = ring.split();

    let input_stream = focusrite.build_input_stream(
        config,
        move |data: &[i32], _info| {
            for frame in data.chunks(2) {
                let input_1 = frame[0];
                let _ = producer.try_push(input_1);
            }
        },
        move |err| {
            eprintln!("INPUT ERROR: {err}");
        },
        None,
    )?;

    let output_stream = focusrite.build_output_stream(
        config,
        move |data: &mut [i32], _info| {
            for frame in data.chunks_mut(2) {
                let sample = consumer.try_pop().unwrap_or(0);

                frame[0] = sample;
                frame[1] = sample;
            }
        },
        move |err| {
            eprintln!("OUTPUT ERROR: {err}");
        },
        None,
    )?;

    input_stream.play()?;
    output_stream.play()?;

    println!("Running...");
    println!("Focusrite Input 1 -> Output 1");
    println!("Press Ctrl+C to stop.");

    loop {
        std::thread::sleep(Duration::from_secs(1));
    }
    Ok(())
}

Cargo.toml:

[dependencies]
anyhow = "1.0.104"
cpal = { version = "0.18.2", features = ["asio"] }
ringbuf = "0.5.2"

Observed

After a few minutes of continuous audio, the input callback thread panics:

thread '<unnamed>' (8468) panicked at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\cpal-0.18.2\src\host\asio\stream.rs:44:13:
attempt to add with overflow
error: process didn't exit successfully: target\debug\guitar_host.exe (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)

Full stacktrace:

thread '<unnamed>' (3184) panicked at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\cpal-0.18.2\src\host\asio\stream.rs:44:13:
attempt to add with overflow
stack backtrace:
   0:     0x7ff60f33f689 - std::backtrace_rs::backtrace::win64::trace
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\..\..\backtrace\src\backtrace\win64.rs:85
   1:     0x7ff60f33f689 - std::backtrace_rs::backtrace::trace_unsynchronized
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66
   2:     0x7ff60f33f689 - std::sys::backtrace::_print_fmt
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\sys\backtrace.rs:74
   3:     0x7ff60f33f689 - std::sys::backtrace::impl$0::print::impl$0::fmt
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\sys\backtrace.rs:44
   4:     0x7ff60f34dca1 - core::fmt::write
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\core\src\fmt\mod.rs:0
   5:     0x7ff60f342f24 - std::io::default_write_fmt
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\io\mod.rs:626
   6:     0x7ff60f342f24 - std::io::Write::write_fmt<std::sys::stdio::windows::Stderr>
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\io\mod.rs:1730
   7:     0x7ff60f337d85 - std::sys::backtrace::BacktraceLock::print
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\sys\backtrace.rs:47
   8:     0x7ff60f337d85 - std::panicking::default_hook::closure$0
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\panicking.rs:292
   9:     0x7ff60f33b5aa - std::panicking::default_hook
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\panicking.rs:319
  10:     0x7ff60f33b7b3 - std::panicking::panic_with_hook
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\panicking.rs:815
  11:     0x7ff60f337e94 - std::panicking::panic_handler::closure$0
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\panicking.rs:681
  12:     0x7ff60f336b9f - std::sys::backtrace::__rust_end_short_backtrace<std::panicking::panic_handler::closure_env$0,never$>
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\sys\backtrace.rs:182
  13:     0x7ff60f3384ee - std::panicking::panic_handler
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\std\src\panicking.rs:679
  14:     0x7ff60f358d6d - core::panicking::panic_fmt
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\core\src\panicking.rs:80
  15:     0x7ff60f358e9e - core::panicking::panic_const::panic_const_add_overflow
                               at /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\core\src\panicking.rs:175
  16:     0x7ff60f2d1004 - cpal::host::asio::stream::TimeBase::to_stream_instant
                               at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\cpal-0.18.2\src\host\asio\stream.rs:44
  17:     0x7ff60f2b8d23 - cpal::host::asio::stream::impl$3::build_input_stream_raw::closure$4<cpal::traits::DeviceTrait::build_input_stream::closure_env$0<cpal::platform::platform_impl::Device,i32,guitar_host::main::closure_env$2,guitar_host::main::closure_env$3>,guitar_host::main:
                               at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\cpal-0.18.2\src\host\asio\stream.rs:253
  18:     0x7ff60f3232c3 - alloc::boxed::impl$32::call_mut<tuple$<ref$<asio_sys::bindings::CallbackInfo> >,dyn$<core::ops::function::FnMut<tuple$<ref$<asio_sys::bindings::CallbackInfo> >,assoc$<Output,tuple$<> > >,core::marker::Send>,alloc::alloc::Global>
                               at C:\Users\Zack\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\boxed.rs:2326
  19:     0x7ff60f3286d8 - asio_sys::bindings::BufferCallback::run
                               at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\asio-sys-0.4.0\src\bindings\mod.rs:503
  20:     0x7ff60f329c01 - asio_sys::bindings::buffer_switch_time_info
                               at C:\Users\Zack\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\asio-sys-0.4.0\src\bindings\mod.rs:1240
  21:      0x22cadb25056 - DllUnregisterServer
  22:      0x22cadb24812 - DllUnregisterServer
  23:      0x22cadb239ec - DllUnregisterServer
  24:      0x22cadb240ce - DllUnregisterServer
  25:      0x22cadb226c6 - DllGetClassObject
  26:     0x7fff60f1cd30 - wcsrchr
  27:     0x7fff6237cd87 - BaseThreadInitThunk
  28:     0x7fff6376caec - RtlUserThreadStart
error: process didn't exit successfully: `target\debug\guitar_host.exe` (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)

Expected

No panic; timestamps should remain correct (or at least not overflow) for
long-running streams, so it does not panic in dev mode (since release mode seems and sounds like it works just fine).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions