-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Open
Labels
A-tokioArea: The main tokio crateArea: The main tokio crate
Description
Version
tokio v1.47.1
tokio-macros v2.5.0 (proc-macro)
Platform
Linux hostname 6.11.0-25-generic #25~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 17:20:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
Description
When the following rust program is run under strace there is an additional single byte write(4, "\1\0\0\0\0\0\0\0", 8)
syscall when a request is made with curl http://localhost:8000
#!/usr/bin/env -S cargo +nightly -Zscript
---
[dependencies]
tokio = { version = "1.47.1", features = ["full"] }
---
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener;
#[tokio::main(flavor = "current_thread")]
async fn main() {
let addr = "127.0.0.1:8000".to_string();
let server = TcpListener::bind(&addr).await.unwrap();
loop {
let (mut stream, _) = server.accept().await.unwrap();
tokio::spawn(async move {
let mut req = [0; 4096];
let _bytes_read = stream.read(&mut req).await.unwrap();
stream
.write_all(
b"HTTP/1.1 200 OK\r\n\
Connection: close\r\n\
Content-Type: text/plain; charset=utf-8\r\n\
\r\n\
Hello, World!",
)
.await
.unwrap();
stream.shutdown().await.unwrap_or_default();
});
}
}
strace output for a single curl:
epoll_wait(3, [{events=EPOLLIN, data={u32=1061629696, u64=99558403550976}}], 1024, -1) = 1
write(4, "\1\0\0\0\0\0\0\0", 8) = 8
accept4(9, {sa_family=AF_INET, sin_port=htons(50978), sin_addr=inet_addr("127.0.0.1")}, [128 => 16], SOCK_CLOEXEC|SOCK_NONBLOCK) = 10
epoll_ctl(5, EPOLL_CTL_ADD, 10, {events=EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, data={u32=1061630080, u64=99558403551360}}) = 0
accept4(9, 0x7ffc5e4a3c70, [128], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(3, [{events=EPOLLIN, data={u32=0, u64=0}}, {events=EPOLLIN|EPOLLOUT, data={u32=1061630080, u64=99558403551360}}], 1024, -1) = 2
recvfrom(10, "GET / HTTP/1.1\r\nHost: localhost:"..., 4096, 0, NULL, NULL) = 77
sendto(10, "HTTP/1.1 200 OK\r\nConnection: clo"..., 92, MSG_NOSIGNAL, NULL, 0) = 92
shutdown(10, SHUT_WR) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 10, NULL) = 0
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
This does not happen when I rt.spawn
the future before calling rt.block_on
.
#!/usr/bin/env -S cargo +nightly -Zscript
---
[dependencies]
tokio = { version = "1.47.1", features = ["full"] }
---
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener;
fn main() {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
// Spawn future to avoid extra single byte write syscall per loop.
let future = rt.spawn(async {
let addr = "127.0.0.1:8000".to_string();
let server = TcpListener::bind(&addr).await.unwrap();
loop {
let (mut stream, _) = server.accept().await.unwrap();
tokio::spawn(async move {
let mut req = [0; 4096];
let _bytes_read = stream.read(&mut req).await.unwrap();
stream
.write_all(
b"HTTP/1.1 200 OK\r\n\
Connection: close\r\n\
Content-Type: text/plain; charset=utf-8\r\n\
\r\n\
Hello, World!",
)
.await
.unwrap();
stream.shutdown().await.unwrap_or_default();
});
}
});
rt.block_on(future).unwrap();
}
strace output for a single curl without additional single byte write syscall:
epoll_wait(3, [{events=EPOLLIN, data={u32=3591807232, u64=102004770119936}}], 1024, -1) = 1
accept4(9, {sa_family=AF_INET, sin_port=htons(52860), sin_addr=inet_addr("127.0.0.1")}, [128 => 16], SOCK_CLOEXEC|SOCK_NONBLOCK) = 10
epoll_ctl(5, EPOLL_CTL_ADD, 10, {events=EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, data={u32=3591807616, u64=102004770120320}}) = 0
accept4(9, 0x7ffcf2c12a30, [128], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(3, [{events=EPOLLIN|EPOLLOUT, data={u32=3591807616, u64=102004770120320}}], 1024, -1) = 1
recvfrom(10, "GET / HTTP/1.1\r\nHost: localhost:"..., 4096, 0, NULL, NULL) = 77
sendto(10, "HTTP/1.1 200 OK\r\nConnection: clo"..., 92, MSG_NOSIGNAL, NULL, 0) = 92
shutdown(10, SHUT_WR) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 10, NULL) = 0
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
Possibly related to #2287 but here I'm using the current_thread runtime so there seems little reason to wake thread.
fwsGonzo
Metadata
Metadata
Assignees
Labels
A-tokioArea: The main tokio crateArea: The main tokio crate