Hi, On 23.05.2018 14:15, Alexander Kurtz wrote: > [Please keep me CC'ed; I'm not subscribed to the list] > > Hi! > > The program shown below (also available at [0]) does the following: > > * Create two sockets > * Enable SO_REUSEADDR on both > * Bind both sockets to [::1]:12345 > * Spawn two threads which both call listen(2) on one socket each > * Check that at least one thread succeeded > > Unfortunately, when running this program on Linux 4.16, it is sometimes > possible that neither thread succeeds in calling listen(2): > > $ uname -a > Linux shepard 4.16.0-1-amd64 #1 SMP Debian 4.16.5-1 (2018-04-29) x86_64 > GNU/Linux > $ time make > cc -Wall -Wextra -pedantic -Werror -O3 listenrace.c -lpthread -o > listenrace > for i in `seq 10000`; do ./listenrace; done > listenrace: listenrace.c:58: main: Assertion `result1 == 0 || result2 == > 0' failed. > Aborted > listenrace: listenrace.c:58: main: Assertion `result1 == 0 || result2 == > 0' failed. > Aborted > listenrace: listenrace.c:58: main: Assertion `result1 == 0 || result2 == > 0' failed. > Aborted > > real 0m8.201s > user 0m6.801s > sys 0m2.141s > $ > > As can be seen, on 3 runs (out of 10000) calling listen(2) failed in > *both* threads. Is this to be expected (i.e. "don't do this then") or > could this be some race condition in the Linux kernel?
At the first sight, it is in kernel and is expected: inet_csk_listen_start() { /* There is race window here: we announce ourselves listening, * but this transition is still not validated by get_port(). * It is OK, because this socket enters to hash table only * after validation is complete. */ inet_sk_state_store(sk, TCP_LISTEN); if (!sk->sk_prot->get_port(sk, inet->inet_num)) { } CC netdev. Kirill