Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

memory leak in tcp client when repeatedly writing holding register #301

Closed
fbrisa opened this issue Nov 25, 2024 · 2 comments · Fixed by #302
Closed

memory leak in tcp client when repeatedly writing holding register #301

fbrisa opened this issue Nov 25, 2024 · 2 comments · Fixed by #302

Comments

@fbrisa
Copy link

fbrisa commented Nov 25, 2024

Hi, I think I found a memory leak bug:

I have a program that makes 2 holding register writes:
first call writes a value
second call writes 2 values (problem happens even with more number of values)

if you keep doing that, program will continue to double the ram needed because of this line in
src/coded/tcp.rs (line 136)
buf.reserve((buf.capacity() - buf_offset) + request_pdu_size + 7);

this happens on every iteration, you will see an initial 8KB usage than 16KB and so on till the program crashes

it does not matter that the server answers, problem will occur eventually

@fbrisa
Copy link
Author

fbrisa commented Nov 25, 2024

Here an example on how to see the error:

it is the tpc client example with a infinite loop, to make the 2 calls:

on my pc crashes at iteration 21 saying:

memory allocation of 34359738368 bytes failed

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    use tokio_modbus::prelude::*;

    let socket_addr = "127.0.0.1:5502".parse().unwrap();

    let mut ctx = tcp::connect(socket_addr).await?;

    let mut idx=1;
    loop {
        println!("Iteration {}", idx);
        ctx.write_multiple_registers(0x1000, &[1]).await??;
        ctx.write_multiple_registers(0x1000, &[1,2]).await??;

        idx+=1;
    }

    // it will never land here

    println!("Disconnecting");
    ctx.disconnect().await?;

    Ok(())
}

cdbennett added a commit to cdbennett/tokio-modbus that referenced this issue Nov 27, 2024
The call to `BytesMut::reserve()` was passing the total number of bytes we
desired as the capacity, but `reserve()` takes only the additional number of
bytes we expect to insert. This was resulting in an exponential explosion of
the length and a crash after a couple dozen calls at most, with a message like

    memory allocation of 34359738368 bytes failed

Fixes slowtec#301
@cdbennett
Copy link
Contributor

It appears this issue was introduced in main with #292, and it seems that it did not affect v0.15.0 or earlier.

cdbennett added a commit to cdbennett/tokio-modbus that referenced this issue Nov 28, 2024
The call to `BytesMut::reserve()` was passing the total number of bytes we
desired as the capacity, but `reserve()` takes only the additional number of
bytes we expect to insert. This was resulting in an exponential explosion of
the length and a crash after a couple dozen calls at most, with a message like

    memory allocation of 34359738368 bytes failed

Fixes slowtec#301
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants