From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Miller Subject: Re: [PATCH v2 net-next] af_unix: ensure POLLOUT on remote close() for connected dgram socket Date: Fri, 03 Aug 2018 16:44:44 -0700 (PDT) Message-ID: <20180803.164444.8668116949268659.davem@davemloft.net> References: <1533331493-26286-1-git-send-email-jbaron@akamai.com> Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: netdev@vger.kernel.org, rientjes@google.com, rweikusat@mobileactivedefense.com, edumazet@google.com To: jbaron@akamai.com Return-path: Received: from shards.monkeyblade.net ([23.128.96.9]:42374 "EHLO shards.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731955AbeHDBnK (ORCPT ); Fri, 3 Aug 2018 21:43:10 -0400 In-Reply-To: <1533331493-26286-1-git-send-email-jbaron@akamai.com> Sender: netdev-owner@vger.kernel.org List-ID: From: Jason Baron Date: Fri, 3 Aug 2018 17:24:53 -0400 > Applications use -ECONNREFUSED as returned from write() in order to > determine that a socket should be closed. However, when using connected > dgram unix sockets in a poll/write loop, a final POLLOUT event can be > missed when the remote end closes. Thus, the poll is stuck forever: > > thread 1 (client) thread 2 (server) > > connect() to server > write() returns -EAGAIN > unix_dgram_poll() > -> unix_recvq_full() is true > close() > ->unix_release_sock() > ->wake_up_interruptible_all() > unix_dgram_poll() (due to the > wake_up_interruptible_all) > -> unix_recvq_full() still is true > ->free all skbs > > > Now thread 1 is stuck and will not receive anymore wakeups. In this > case, when thread 1 gets the -EAGAIN, it has not queued any skbs > otherwise the 'free all skbs' step would in fact cause a wakeup and > a POLLOUT return. So the race here is probably fairly rare because > it means there are no skbs that thread 1 queued and that thread 1 > schedules before the 'free all skbs' step. > > This issue was reported as a hang when /dev/log is closed. > > The fix is to signal POLLOUT if the socket is marked as SOCK_DEAD, which > means a subsequent write() will get -ECONNREFUSED. > > Reported-by: Ian Lance Taylor > Cc: David Rientjes > Cc: Rainer Weikusat > Cc: Eric Dumazet > Signed-off-by: Jason Baron > --- > v2: use check for SOCK_DEAD, since skb's can be purged in unix_sock_destructor() Applied, thanks Jason.