From patchwork Wed Aug 25 02:05:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KOSAKI Motohiro X-Patchwork-Id: 62648 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 03F52B70DA for ; Wed, 25 Aug 2010 12:06:21 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932243Ab0HYCFw (ORCPT ); Tue, 24 Aug 2010 22:05:52 -0400 Received: from fgwmail5.fujitsu.co.jp ([192.51.44.35]:42640 "EHLO fgwmail5.fujitsu.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932087Ab0HYCFv (ORCPT ); Tue, 24 Aug 2010 22:05:51 -0400 Received: from m1.gw.fujitsu.co.jp ([10.0.50.71]) by fgwmail5.fujitsu.co.jp (Fujitsu Gateway) with ESMTP id o7P25njn023288 (envelope-from kosaki.motohiro@jp.fujitsu.com); Wed, 25 Aug 2010 11:05:50 +0900 Received: from smail (m1 [127.0.0.1]) by outgoing.m1.gw.fujitsu.co.jp (Postfix) with ESMTP id 7A29545DE52; Wed, 25 Aug 2010 11:05:49 +0900 (JST) Received: from s1.gw.fujitsu.co.jp (s1.gw.fujitsu.co.jp [10.0.50.91]) by m1.gw.fujitsu.co.jp (Postfix) with ESMTP id 4D79345DE50; Wed, 25 Aug 2010 11:05:49 +0900 (JST) Received: from s1.gw.fujitsu.co.jp (localhost.localdomain [127.0.0.1]) by s1.gw.fujitsu.co.jp (Postfix) with ESMTP id 2DDD3E38003; Wed, 25 Aug 2010 11:05:49 +0900 (JST) Received: from m107.s.css.fujitsu.com (m107.s.css.fujitsu.com [10.249.87.107]) by s1.gw.fujitsu.co.jp (Postfix) with ESMTP id D9B521DB804F; Wed, 25 Aug 2010 11:05:48 +0900 (JST) Received: from m107.css.fujitsu.com (m107 [127.0.0.1]) by m107.s.css.fujitsu.com (Postfix) with ESMTP id 9DD55670004; Wed, 25 Aug 2010 11:05:48 +0900 (JST) Received: from [127.0.0.1] (unknown [10.124.102.29]) by m107.s.css.fujitsu.com (Postfix) with ESMTP id 34B3A670001; Wed, 25 Aug 2010 11:05:48 +0900 (JST) X-SecurityPolicyCheck-FJ: OK by FujitsuOutboundMailChecker v1.3.1 Received: from KOSANOTE2[10.124.102.29] by KOSANOTE2 (FujitsuOutboundMailChecker v1.3.1/9992[10.124.102.29]); Wed, 25 Aug 2010 11:05:48 +0900 (JST) From: KOSAKI Motohiro To: netdev@vger.kernel.org, LKML Subject: [PATCH] tcp: select(writefds) don't hang up when a peer close connection Cc: kosaki.motohiro@jp.fujitsu.com, YOSHIFUJI Hideaki Message-Id: <20100825110049.F3C9.A69D9226@jp.fujitsu.com> MIME-Version: 1.0 X-Mailer: Becky! ver. 2.50.07 [ja] Date: Wed, 25 Aug 2010 11:05:48 +0900 (JST) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This issue come from ruby language community. Below test program hang up when only run on Linux. % uname -mrsv Linux 2.6.26-2-486 #1 Sat Dec 26 08:37:39 UTC 2009 i686 % ruby -rsocket -ve ' BasicSocket.do_not_reverse_lookup = true serv = TCPServer.open("127.0.0.1", 0) s1 = TCPSocket.open("127.0.0.1", serv.addr[1]) s2 = serv.accept s2.close s1.write("a") rescue p $! s1.write("a") rescue p $! Thread.new { s1.write("a") }.join' ruby 1.9.3dev (2010-07-06 trunk 28554) [i686-linux] # [Hang Here] FreeBSD, Solaris, Mac doesn't. because Ruby's write() method call select() internally. and tcp_poll has a bug. SUS defined 'ready for writing' of select() as following. | A descriptor shall be considered ready for writing when a call to an output | function with O_NONBLOCK clear would not block, whether or not the function | would transfer data successfully. That said, EPIPE situation is clearly one of 'ready for writing'. We don't have read-side issue because tcp_poll() already has read side shutdown care. | if (sk->sk_shutdown & RCV_SHUTDOWN) | mask |= POLLIN | POLLRDNORM | POLLRDHUP; So, Let's insert same logic in write side. - reference url http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/31065 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/31068 Signed-off-by: KOSAKI Motohiro --- net/ipv4/tcp.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 176e11a..2497e48 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -451,7 +451,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) mask |= POLLOUT | POLLWRNORM; } - } + } else + mask |= POLLOUT | POLLWRNORM; if (tp->urg_data & TCP_URG_VALID) mask |= POLLPRI;