Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

monoio支持h1的with_upgrades出现异常 #331

Open
xj524598 opened this issue Feb 2, 2025 · 1 comment
Open

monoio支持h1的with_upgrades出现异常 #331

xj524598 opened this issue Feb 2, 2025 · 1 comment

Comments

@xj524598
Copy link

xj524598 commented Feb 2, 2025

代码如下:

//! HTTP server example with hyper in poll-io mode.
//!
//! After running this example, you can open http://localhost:23300
//! and http://localhost:23300/monoio in your browser or curl it.

use std::net::SocketAddr;

use bytes::Bytes;
use futures::Future;
use hyper::{server::conn::http1, service::service_fn};
use monoio::{io::IntoPollIo, net::TcpListener};

pub(crate) async fn serve_http<S, F, E, A>(addr: A, service: S) -> std::io::Result<()>
where
S: Copy + Fn(Requesthyper::body::Incoming) -> F + 'static,
F: Future<Output = Result<Response<Full>, E>> + 'static,
E: std::error::Error + 'static + Send + Sync,
A: Into,
{
let listener = TcpListener::bind(addr.into())?;
loop {
let (stream, _) = listener.accept().await?;
let stream_poll = monoio_compat::hyper::MonoioIo::new(stream.into_poll_io()?);
monoio::spawn(async move {
// Handle the connection from the client using HTTP1 and pass any
// HTTP requests received on that connection to the hello function
if let Err(err) = http1::Builder::new()
.timer(monoio_compat::hyper::MonoioTimer)
.serve_connection(stream_poll, service_fn(service))
.with_upgrades()
.await
{
println!("Error serving connection: {:?}", err);
}
});
}
}

use http_body_util::Full;
use hyper::{Method, Request, Response, StatusCode};

async fn hyper_handler(
req: Requesthyper::body::Incoming,
) -> Result<Response<Full>, std::convert::Infallible> {
match (req.method(), req.uri().path()) {
(&Method::GET, "/") => Ok(Response::new(Full::new(Bytes::from("Hello World!")))),
(&Method::GET, "/monoio") => Ok(Response::new(Full::new(Bytes::from("Hello Monoio!")))),
_ => Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Full::new(Bytes::from("404 not found")))
.unwrap()),
}
}

#[monoio::main(threads = 2, timer_enabled = true)]
async fn main() {
println!("Running http server on 0.0.0.0:23300");
let _ = serve_http(([0, 0, 0, 0], 23300), hyper_handler).await;
println!("Http server stopped");
}

错误如下:

error[E0277]: Rc<monoio::driver::shared_fd::Inner> cannot be sent between threads safely
--> src/main.rs:30:18
|
30 | .with_upgrades()
| ^^^^^^^^^^^^^ Rc<monoio::driver::shared_fd::Inner> cannot be sent between threads safely
|
= help: within MonoioIo<TcpStreamPoll>, the trait std::marker::Send is not implemented for Rc<monoio::driver::shared_fd::Inner>, which is required by MonoioIo<TcpStreamPoll>: std::marker::Send
note: required because it appears within the type monoio::driver::shared_fd::SharedFd
--> /Users/10010268/.cargo/registry/src/index.crates.io-6f17d22bba15001f/monoio-0.2.4/src/driver/shared_fd.rs:16:19
|
16 | pub(crate) struct SharedFd {
| ^^^^^^^^
note: required because it appears within the type monoio::net::TcpStream
--> /Users/10010268/.cargo/registry/src/index.crates.io-6f17d22bba15001f/monoio-0.2.4/src/net/tcp/stream.rs:70:12
|
70 | pub struct TcpStream {
| ^^^^^^^^^
note: required because it appears within the type TcpStreamPoll
--> /Users/10010268/.cargo/registry/src/index.crates.io-6f17d22bba15001f/monoio-0.2.4/src/net/tcp/stream_poll.rs:23:12
|
23 | pub struct TcpStreamPoll(TcpStream);
| ^^^^^^^^^^^^^
note: required because it appears within the type MonoioIo<TcpStreamPoll>
--> /Users/10010268/.cargo/registry/src/index.crates.io-6f17d22bba15001f/monoio-compat-0.2.2/src/hyper.rs:80:16
|
80 | pub struct MonoioIo {
| ^^^^^^^^
note: required by a bound in hyper::server::conn::http1::Connection::<I, S>::with_upgrades
--> /Users/10010268/.cargo/registry/src/index.crates.io-6f17d22bba15001f/hyper-1.6.0/src/server/conn/http1.rs:193:12
|
191 | pub fn with_upgrades(self) -> UpgradeableConnection<I, S>
| ------------- required by a bound in this associated function
192 | where
193 | I: Send,
| ^^^^ required by this bound in Connection::<I, S>::with_upgrades
help: consider removing this method call, as the receiver has type &mut hyper::server::conn::http1::Builder and &mut hyper::server::conn::http1::Builder: std::marker::Send trivially holds
|
28 - .timer(monoio_compat::hyper::MonoioTimer)
29 - .serve_connection(stream_poll, service_fn(service))
28 + .timer(monoio_compat::hyper::MonoioTimer)
|

@ihciah
Copy link
Member

ihciah commented Feb 5, 2025

这个问题出在 hyper 对于 upgrade 的更严格的要求上。
我个人认为这个 Send 约束理论上可能是不必要的,这可能和其内部设计有关。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants