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

Weird non-blocking block when using two nested tokio::spawn statements #703

Closed
George3d6 opened this issue Oct 15, 2018 · 4 comments
Closed

Comments

@George3d6
Copy link

George3d6 commented Oct 15, 2018

Version 0.1.11

Platform Linux 4.18.9-arch1-1-ARCH #1 SMP PREEMPT Wed Sep 19 21:19:17 UTC 2018 x86_64 GNU/Linux

Description

I'm trying to write a tokio tcp listener in a rather straight forward manner:

    let addr = "127.0.0.1:5282".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");

    let server = listener.incoming()
      .map_err(|e| eprintln!("Err {:?}", e))
      .for_each(|sock| {
            let (reader, writer) = sock.split();
            let mut buffer = Vec::new();
            let reader = read_to_end(reader, buffer).map(|(_,_buf)| {
                let b = b"Hello world";
                let writer = write_all(writer, b).map(|_| {
                }).map_err(|err| {
                    // @ Err
                    eprintln!("Err {:?}", err);
                });
                //@2
                tokio::spawn(writer);
            }).map_err(|err| {
                eprintln!("Err {:?}", err);
            });
            // @1
            tokio::spawn(reader)
    });

    tokio::run(server);

My expectation with this code would be to be able to do something like:

echo whatever | netcat localhost 5282 and get back the message Hello world

However, what happens, is that I send a string of characters via netact or via telent and get nothing...
The execution is "stuck" at the point in the code I marked with @1. The loop is not blocked, since I'm well able to send another request and have it reach the @1 point, but it seems like the task tokio::spawn(reader) is not actually getting spawned.

Even weirder, when I close the connection I actually get the error that I'm printing out at the @ Err mark in the code.

This behavior is rather weird. Am I doing something (obviously) wrong here or is this a bug/unexpected behavior of some sort ?

I mean... I am not blocking the event loop and I'm seemingly not "waiting" for anything, so why wouldn't the server progress to spawning the writer future before the connection is closed ?

@carllerche
Copy link
Member

Are you able to post the full code, including externs and use statements?

@George3d6
Copy link
Author

George3d6 commented Oct 15, 2018

extern crate tokio;

use tokio::prelude::*;
use tokio::io::{write_all, read_to_end};
use tokio::net::TcpListener;

use std::collections::HashMap;
use std::string::String;
use std::vec::Vec;

fn main() {
    let addr = "127.0.0.1:5282".parse().unwrap();
    let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");

    let server = listener.incoming()
      .map_err(|e| eprintln!("Err {:?}", e))
      .for_each(|sock| {
            let (reader, writer) = sock.split();
            let mut buffer = Vec::new();
            let reader = read_to_end(reader, buffer).map(|(_,_buf)| {
                let b = b"Hello world";
                let writer = write_all(writer, b).map(|_| {
                }).map_err(|err| {
                    // @ Err
                    eprintln!("Err {:?}", err);
                });
                //@2
                tokio::spawn(writer);
            }).map_err(|err| {
                eprintln!("Err {:?}", err);
            });
            // @1
            tokio::spawn(reader)
    });

    tokio::run(server);
}

@George3d6
Copy link
Author

That is all the code I need to reproduce this... ahm, happening (not sure if bug).

Also, if relevant, rustc 1.29.0

@George3d6 George3d6 reopened this Oct 15, 2018
@George3d6
Copy link
Author

Sorry, figured out what was wrong, I was essentially using read_to_end where something like lines should be used. As far as I understand the "end" in read to end essentially means when the connection is closed (hence why I was obviously unable to write to said connection when the read was over).

Seems silly in hindsight, my apologies.

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