tokio-rs / tokio

A runtime for writing reliable asynchronous applications with Rust. Provides I/O, networking, scheduling, timers, ...
https://tokio.rs
MIT License
26.42k stars 2.43k forks source link

TcpStream cannot write more than 5760 bytes on ESP32 #6805

Open victorbnl opened 2 weeks ago

victorbnl commented 2 weeks ago

Version

tokio-tcplistener-issue v0.1.0 (/home/victor/dev/tokio-tcplistener-issue)
└── tokio v1.39.3

Platform

Linux Victor-Laptop 6.10.3-arch1-2 #1 SMP PREEMPT_DYNAMIC Tue, 06 Aug 2024 07:21:19 +0000 x86_64 GNU/Linux

Code running on an Ai Thinker ESP32-CAM

Description

The code below prints "Wrote 5760 bytes" and blocks forever on the next call to write. I expect it to write all the 8000 bytes to the TCP stream.

Adding a call to flush right after writing does not solve the problem.

The issue happens too with write_all (it blocks forever). It doesn’t occur on a std::net::TcpListener.

Code Required tokio features: `io-util,net,rt` ```rs use std::thread; use esp_idf_svc::{wifi, eventloop, nvs}; use esp_idf_svc::io::vfs; use esp_idf_svc::hal::peripherals; use tokio::net::TcpListener; use tokio::io::AsyncWriteExt; fn main() { esp_idf_svc::sys::link_patches(); esp_idf_svc::log::EspLogger::initialize_default(); let peripherals = peripherals::Peripherals::take().unwrap(); let sys_loop = eventloop::EspSystemEventLoop::take().unwrap(); let nvs = nvs::EspDefaultNvsPartition::take().unwrap(); let mut wifi = wifi::BlockingWifi::wrap( wifi::EspWifi::new(peripherals.modem, sys_loop.clone(), Some(nvs)).unwrap(), sys_loop, ).unwrap(); let wifi_configuration = wifi::Configuration::AccessPoint(wifi::AccessPointConfiguration { ssid: "ESP32".try_into().unwrap(), password: "PASSWORD".try_into().unwrap(), ..Default::default() }); wifi.set_configuration(&wifi_configuration).unwrap(); wifi.start().unwrap(); wifi.wait_netif_up().unwrap(); vfs::initialize_eventfd(5).unwrap(); thread::Builder::new() .stack_size(60_000) .spawn(|| { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() .block_on(async { let listener = TcpListener::bind("0.0.0.0:8080").await.unwrap(); loop { let (mut stream, _) = listener.accept().await.unwrap(); let data = [1; 8000]; let mut written = 0; while written < 8000 { written += stream.write(&data[written..]).await.unwrap(); println!("Wrote {} bytes", written); } } }); }).unwrap(); core::mem::forget(wifi); } ```
Darksonn commented 2 weeks ago

What is it connecting to? Is the peer reading the data?

victorbnl commented 1 week ago

What connects to this server is just a simple TCP client on my computer that reads exactly 8000 bytes of data and writes it to a file. I can confirm it reads it because with a std::net::TcpListener, the full data is written. With tokio, however, the client is stuck forever on read_exact (or, if using read, reads 5760 bytes and gets stuck on the next read).

Darksonn commented 1 week ago

Well, could you share the client?