seastar::repeat

60 views
Skip to first unread message

giovibal@gmail.com

<giovibal@gmail.com>
unread,
Jul 30, 2017, 2:01:49 PM7/30/17
to seastar-dev
I'm new to seastar, maybe this question is trivial.

I'm studing seastar, in the networking tutorial (http://docs.seastar-project.org/master/md_doc_tutorial.html
while I'm testing the function "handle_connection", i've put an out debug of buf.size() during socket read;
why if i send a lot of chars (throught telnet localhost 1234), server logs always max 4097, and response returned is truncated ?

I expect that repeat to continue till buffer eof...

Thank you in advice! 

This is the function with my debug log:

seastar::future<> handle_connection(seastar::connected_socket s,
seastar::socket_address a) {
auto out = s.output();
auto in = s.input();
return do_with(std::move(s), std::move(out), std::move(in),
[] (auto& s, auto& out, auto& in) {
return seastar::repeat([&out, &in] {
return in.read().then([&out] (auto buf) {
if (buf) {
std::cout << buf.size() << std::endl;
return out.write(std::move(buf)).then([&out] {
return out.flush();
}).then([] {
return stop_iteration::no;
});
} else {
return seastar::make_ready_future<seastar::stop_iteration>(
seastar::stop_iteration::yes);
}
});
}).then([&out] {
return out.close();
});
});
}

Nadav Har'El

<nyh@scylladb.com>
unread,
Jul 30, 2017, 5:59:32 PM7/30/17
to Giovanni Baleani, seastar-dev
On Sun, Jul 30, 2017 at 9:01 PM, <giov...@gmail.com> wrote:
I'm new to seastar, maybe this question is trivial.

I'm studing seastar, in the networking tutorial (http://docs.seastar-project.org/master/md_doc_tutorial.html
while I'm testing the function "handle_connection", i've put an out debug of buf.size() during socket read;
why if i send a lot of chars (throught telnet localhost 1234), server logs always max 4097, and response returned is truncated ?

If I understand correctly, the code below is a verbatim copy of the one in the tutorial, implementing the RFC 862 echo server.
I just tested that code on my machine, and it seems the loop does work as expected, and doesn't stop after 4097 characters. For example,

/home/nyh/seastar$ dd if=/dev/zero bs=1 count=1000000 | nc localhost 1234 | wc -c
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB, 977 KiB) copied, 0.433434 s, 2.3 MB/s
1000000
 
Here you can see "dd" outputting one million bytes into a pipe which "nc" send to a connection to port 1234, and we measure the number of characters in the output from nc (what we get back from the server) to be again one million bytes.

So I don't know why your version doesn't work as expected. It looks correct! (and it looks the same code as the tutorial, which seems to work).

Can you attach a complete test program which fails and the exact command line to test it?

Are you using Seastar's standard Linux networking support (that's what I am using), or DPDK?

By the way, what happens after 4097 bytes? Does the server continue reading but discarding the bytes? Or does it hang up the connection prematurely (and cause the sending process to get a broken pipe)? Or what?

--
You received this message because you are subscribed to the Google Groups "seastar-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to seastar-dev+unsubscribe@googlegroups.com.
To post to this group, send email to seast...@googlegroups.com.
Visit this group at https://groups.google.com/group/seastar-dev.
To view this discussion on the web visit https://groups.google.com/d/msgid/seastar-dev/c1787776-382d-471c-b00e-12bafa863b31%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

giovibal@gmail.com

<giovibal@gmail.com>
unread,
Jul 31, 2017, 3:35:59 AM7/31/17
to seastar-dev, giovibal@gmail.com
I'am using telnet command "telnet localhost 1234" and write arbitrary characters with keyboard, 
after i press RETURN, characters are sent to server, which logs 4097.
Using "dd if=/dev/zero bs=1 count=1000000 | nc localhost 1234 | wc -c",
or "cat data.txt | nc localhost 1234 | wc -c" 
it works! 
Maybe it's caused by a telnet stuff (?)

For completness: I'm using standard Linux networking support and start server with -c 1 params.

Thank you for your patience

Nadav Har'El

<nyh@scylladb.com>
unread,
Jul 31, 2017, 4:20:21 AM7/31/17
to Giovanni Baleani, seastar-dev
On Mon, Jul 31, 2017 at 10:35 AM, <giov...@gmail.com> wrote:
I'am using telnet command "telnet localhost 1234" and write arbitrary characters with keyboard, 
after i press RETURN, characters are sent to server, which logs 4097.
Using "dd if=/dev/zero bs=1 count=1000000 | nc localhost 1234 | wc -c",
or "cat data.txt | nc localhost 1234 | wc -c" 
it works! 
Maybe it's caused by a telnet stuff (?)

:-)

If that is what you did in your experiment then it's not at all a bug in Seastar or your program - it's a simple thing you missed about how Linux's terminal devices work, and is only a problem in your specific experiment.

I'll try to explain for the entertainment (?) of the readers, although this really has nothing to do with Seastar.

When you do "telnet localhost 1234", the "telnet" program doesn't use the normal telnet protocol, nor does it put the terminal (tty) in so-called "raw mode" where it receives character by character.

Rather, the "telnet localhost 1234" leaves the terminal in normal, "cooked" (aka canonical - see "icanon" in stty(1)), reads all the text that you type, and sends it to the server.

As usual in cooked mode, the text you type does not get sent immediately to the server character by character, but rather, the telnet program can only read the entire line from the kernel - and sends it over the netwrok - when you type a newline character. Until that time, you have *line editing* capabilities - backspace, word erase (^W), and so on. In UNIX nomenclature, this is known as "line discipline"

For the Linux kernel to implement this line editing, it needs to *buffer* the text you type until the newline. Linux has a constant, N_TTY_BUF_SIZE, which determines the fixed size of this buffer. By now you shouldn't be surprised to hear it is 4096. So after you type more than 4096 characters, the rest will ignored (I'm surprised you even saw them echoed on the screen, by the way, antique versions of UNIX used to echo BELL (\007) characters when the buffer ran out), and when you press newline, the telnet application will read - and will send to the server - exactly 4097 bytes: 4096 characters from the buffer, plus a linefeed character (\n).

There is no way to increase in Linux the size of this buffer, and usually there is no reason to. If you had *newlines* in that text you typed, everything would have worked as you expected. Your only problem is that you tried to type more than 4096 characters without a newline. And obviously, this problem doesn't exist at all when the input doesn't come from the terminal (where this 4096 character limit happens) - if you took your input from a file or a pipe (as in my example), you could have a billion characters without a newline, if you wish.

By the way, in the OS we wrote before Seastar, OSv, there is no such line-buffer limit - our line buffer is a C++ std::deque<char>, so can grow to any length :-) But all other Unix and Linux implementations I'm familiar with had a limit on the terminal line buffer size.

Nadav.

Jesse Haber-Kucharsky

<jhaberku@scylladb.com>
unread,
Jul 31, 2017, 9:05:17 AM7/31/17
to Nadav Har'El, Giovanni Baleani, seastar-dev
On Mon, Jul 31, 2017 at 11:20:20AM +0300, Nadav Har'El wrote:
>
> I'll try to explain for the entertainment (?) of the readers, although this
> really has nothing to do with Seastar.
>

I learn something new every day on this mailing list. :-)

giovibal@gmail.com

<giovibal@gmail.com>
unread,
Jul 31, 2017, 10:16:34 AM7/31/17
to seastar-dev, giovibal@gmail.com
Great! 

Thank you very much, i love to learn new things :)
Reply all
Reply to author
Forward
0 new messages