I think I found it. There was a race in async ICMP error handling when a signal
occurred at the right time. After the system call was restarted there was
no check for an already pending error in the blocking case, after it went
to sleep it never woke up again because no one called sk->error_report again.
This patch should fix it.
Jason, Could you test it please?
David, Alexey, what do you think?
--- linux/net/ipv4/af_inet.c-o Fri Mar 12 22:14:56 1999
+++ linux/net/ipv4/af_inet.c Fri Mar 12 22:22:26 1999
@@ -53,6 +53,7 @@
* David S. Miller : New socket lookup architecture.
* Some other random speedups.
* Cyrus Durgin : Cleaned up file for kmod hacks.
+ * Andi Kleen : Fix inet_stream_connect TCP race.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -617,10 +618,13 @@
sock->state = SS_CONNECTED;
return 0;
}
- if(sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK)) {
- if(sk->err)
+ if(sk->protocol == IPPROTO_TCP) {
+ if (sk->zapped)
+ goto async_error;
+ if(sk->err)
return sock_error(sk);
- return -EALREADY;
+ if (flags & O_NONBLOCK)
+ return -EALREADY;
}
} else {
/* We may need to bind the socket. */
@@ -651,6 +655,7 @@
sock->state = SS_CONNECTED;
if ((sk->state != TCP_ESTABLISHED) && sk->err) {
/* This is ugly but needed to fix a race in the ICMP error handler */
+async_error:
if (sk->protocol == IPPROTO_TCP && sk->zapped) {
lock_sock(sk);
tcp_set_state(sk, TCP_CLOSE);
-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/