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

Unable to schedule when used with net2 library #4547

Closed
b23r0 opened this issue Feb 26, 2022 · 1 comment
Closed

Unable to schedule when used with net2 library #4547

b23r0 opened this issue Feb 26, 2022 · 1 comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.

Comments

@b23r0
Copy link

b23r0 commented Feb 26, 2022

Version
tokio v1.17.0

Platform
Linux Z2CLL6T3K50D7JL 5.10.60.1-microsoft-standard-WSL2 #1 SMP Wed Aug 25 23:20:18 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Description

use tokio::runtime::{Builder , Runtime};
use tokio::sync::mpsc::channel;
use tokio::{self,net::UdpSocket, select};

async fn spawn_in_task(rt : &Runtime){
    let socket = UdpSocket::bind("127.0.0.1:8080").await.unwrap();
    let socket_cli = UdpSocket::bind("127.0.0.1:8081").await.unwrap();
    socket_cli.send_to(&[1,2,3,4] , "127.0.0.1:8080").await.unwrap();
    let ( c_send , mut c_recv) = channel::<i32>(100);
    
    rt.spawn(async move{
            println!("get here1");
    });
    let mut buf = [0; 64 * 1024];
    loop{
        let c_send = c_send.clone();
        select!{
            _ = socket.recv_from(&mut buf) => {
                println!("get here2");
                rt.spawn(async move {
                   println!("get here3");
                   c_send.send(1).await.unwrap(); 
                });
                println!("get here4");
            }
            _ = c_recv.recv() => {
                println!("end");
                break;
            }
        }
    }

    println!("see here");
}

#[tokio::main]
async fn main() {

    std::thread::spawn( || {
        let rt = Builder::new_current_thread().enable_all().build().unwrap();
        rt.block_on(spawn_in_task(&rt));
    }).join().unwrap();
}

Result :

get here1
get here2
get here4
get here3
end
see here

but i use library net2(for SO_REUSEPORT and SO_REUSEADDR) build a socket then use from_std create a tokio's UdpSoket.

use tokio::runtime::{Builder , Runtime};
use tokio::sync::mpsc::channel;
use tokio::{self,net::UdpSocket, select};
use net2::{UdpBuilder};
use net2::unix::{UnixUdpBuilderExt};

async fn spawn_in_task(rt : &Runtime){
    let local_socket = match UdpBuilder::new_v4().unwrap()
        .reuse_address(true).unwrap()
        .reuse_port(true).unwrap()
        .bind("127.0.0.1:8080") {
            Ok(p) => p,
            Err(_) => {
                return;
            },
        };

    let socket = UdpSocket::from_std(local_socket).unwrap();
    let socket_cli = UdpSocket::bind("127.0.0.1:8081").await.unwrap();
    socket_cli.send_to(&[1,2,3,4] , "127.0.0.1:8080").await.unwrap();
    let ( c_send , mut c_recv) = channel::<i32>(100);
    
    rt.spawn(async move{
            println!("get here1");
    });
    let mut buf = [0; 64 * 1024];
    loop{
        let c_send = c_send.clone();
        select!{
            _ = socket.recv_from(&mut buf) => {
                println!("get here2");
                println!("get here3");
                rt.spawn(async move {
                   println!("get here4");
                   c_send.send(1).await.unwrap(); 
                });
                println!("get here5");
            }
            _ = c_recv.recv() => {
                println!("end");
                break;
            }
        }
    }

    println!("see here");
}

#[tokio::main]
async fn main() {

    std::thread::spawn( || {
        let rt = Builder::new_current_thread().enable_all().build().unwrap();
        rt.block_on(spawn_in_task(&rt));
    }).join().unwrap();
}

Result :

get here1
get here2
get here3
get here5
//stuck here

in after recvfrom , rt.spawn() not getting scheduled execution. i think the problem maybe a bug of tokio.

@b23r0 b23r0 added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Feb 26, 2022
@Darksonn
Copy link
Contributor

As documented on UdpSocket::from_std, it is your responsibility to set the non-blocking option on the socket. If you don't, the socket wont work.


Unrelated, but this doesn't make any sense:

#[tokio::main]
async fn main() {

    std::thread::spawn( || {
        let rt = Builder::new_current_thread().enable_all().build().unwrap();
        rt.block_on(spawn_in_task(&rt));
    }).join().unwrap();
}

The #[tokio::main] macro already creates a runtime. Why are you creating two runtimes? If you want a current-thread runtime, do this:

#[tokio::main(flavor = "current_thread")]
async fn main() {
    spawn_in_task().await;
}

or don't use the #[tokio::main] macro at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

2 participants