From: "Askar Safin" <safinaskar@mail.ru>
To: linux-kernel@vger.kernel.org
Subject: TCP connections come in wrong order
Date: Mon, 02 Feb 2015 00:30:31 +0300 [thread overview]
Message-ID: <1422826231.817940808@f237.i.mail.ru> (raw)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 4539 bytes --]
Consider the following code:
// C99, No error checking for simplicity
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <err.h>
static int
tcp_connect_loop (const char *host, const char *protocol, struct addrinfo *res)
{
for (; res != NULL; res = res->ai_next)
{
int result = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
if (result != -1)
{
if (connect (result, res->ai_addr, res->ai_addrlen) == 0)
{
return result;
}
close (result);
}
}
// SOMEDAY: пеÑаÑаÑÑ Ð±Ð¾Ð»ÑÑе инÑÑ (Ñо же Ð´Ð»Ñ tcp_listen_loop)?
errx (EXIT_FAILURE, "sh_tcp_connect: [%s]:%s: all structs returned by getaddrinfo failed", host, protocol);
}
int //@
sh_tcp_connect (const char *host, const char *protocol, int family)//@;
{
struct addrinfo hints = {};
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *res;
getaddrinfo (host, protocol, &hints, &res);
// POSIX 2013 says that now 'res' list contains at least one item
int result;
result = tcp_connect_loop (host, protocol, res);
freeaddrinfo (res);
return result;
}
static int
tcp_listen_loop (const char *protocol, struct addrinfo *res)
{
for (; res != NULL; res = res->ai_next)
{
int result = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
if (result != -1)
{
const int on = 1;
if (setsockopt (result, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != -1)
{
if (bind (result, res->ai_addr, res->ai_addrlen) == 0)
{
return result;
}
}
close (result);
}
}
errx (EXIT_FAILURE, "sh_tcp_listen: *:%s: all structs returned by getaddrinfo failed", protocol);
}
int //@
sh_tcp_listen (const char *protocol, int family)//@;
{
struct addrinfo hints = {};
hints.ai_flags = AI_PASSIVE;
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *res;
getaddrinfo (NULL, protocol, &hints, &res);
int result;
result = tcp_listen_loop (protocol, res);
listen (result, 5);
freeaddrinfo (res);
return result;
}
#ifndef N
#define N 100000
#endif
int
main (int argc, char *argv[])
{
if (strcmp (argv[1], "-l") == 0)
{
int l = sh_tcp_listen (argv[2], AF_INET);
for (;;)
{
int s = accept (l, NULL, NULL);
if (s == -1)
{
continue;
}
char buf[1000];
write (1, buf, read (s, buf, sizeof (buf)));
close (s);
}
}
else
{
for (int i = 0; i != N; ++i)
{
int s = sh_tcp_connect (argv[1], argv[2], AF_INET);
dprintf (s, "%d\n", i);
close (s);
}
}
exit (EXIT_SUCCESS);
}
Compile this code as, for example, /tmp/x (again: this is C99), then run:
/tmp/x -l 5555 > /tmp/ooo
This command will accept connections and write coming data to /tmp/ooo . Okey, then run in another terminal:
/tmp/x localhost 5555
This command will connect to localhost, write 0, then connect again, write 1, etc. Soon you will not have available ports, so /tmp/x will fail before it will perform all N connections, this is OK.
When this command complete, go to the first terminal and kill the program using Ctrl-C. Then look in /tmp/ooo and notice the last line, let's assume this is 28290. Then compare /tmp/ooo with the right monotonic number sequence:
echo {0..28290} | tr ' ' '\n' | diff -ur - /tmp/ooo
With some luck you will notice that /tmp/ooo is wrong. For example, I got the following:
--- - 2015-02-02 00:24:35.606008461 +0300
+++ /tmp/ooo 2015-02-02 00:09:25.002694629 +0300
@@ -7391,8 +7391,6 @@
7390
7391
7392
-7393
-7394
7395
7396
7397
@@ -7546,6 +7544,8 @@
7545
7546
7547
+7393
+7394
7548
7549
7550
If 'diff' doesn't report difference, then try again and again.
Is this a bug? I think that this is a bug.
Linux ideal-os 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt2-1 (2014-12-08) x86_64 GNU/Linux
Debian 8.0 Jessie
GNU C Library (Debian GLIBC 2.19-13) stable release version 2.19, by Roland McGrath et al.
==
Askar Safin
http://vk.com/safinaskar
Kazan, Russiaÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
next reply other threads:[~2015-02-01 21:30 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-01 21:30 Askar Safin [this message]
2015-02-02 15:07 ` One Thousand Gnomes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1422826231.817940808@f237.i.mail.ru \
--to=safinaskar@mail.ru \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®