From owner-freebsd-net@FreeBSD.ORG Mon Apr 1 15:36:04 2013 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 65A97812; Mon, 1 Apr 2013 15:36:04 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from bigwig.baldwin.cx (bigwig.baldwin.cx [IPv6:2001:470:1f11:75::1]) by mx1.freebsd.org (Postfix) with ESMTP id 45995DC9; Mon, 1 Apr 2013 15:36:04 +0000 (UTC) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id A259BB9B2; Mon, 1 Apr 2013 11:36:03 -0400 (EDT) From: John Baldwin To: freebsd-net@freebsd.org Subject: Re: close(2) while accept(2) is blocked Date: Mon, 1 Apr 2013 11:22:12 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110714-p25; KDE/4.5.5; amd64; ; ) References: <515475C7.6010404@FreeBSD.org> In-Reply-To: <515475C7.6010404@FreeBSD.org> MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201304011122.13101.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.7 (bigwig.baldwin.cx); Mon, 01 Apr 2013 11:36:03 -0400 (EDT) Cc: FreeBSD Hackers , Andriy Gapon X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Apr 2013 15:36:04 -0000 On Thursday, March 28, 2013 12:54:31 pm Andriy Gapon wrote: > > So, this started as a simple question, but the answer was quite unexpected to me. > > Let's say we have an opened and listen-ed socket and let's assume that we know > that one thread is blocked in accept(2) and another thread is calling close(2). > What is going to happen? > > Turns out that practically nothing. For kernel the close call would be almost a nop. > My understanding is this: > - when socket is created, its reference count is 1 > - when accept(2) is called, fget in kernel increments the reference count (kept in > an associated struct file) > - when close(2) is called, the reference count is decremented > > The reference count is still greater than zero, so fdrop does not call fo_close. > That means that in the case of a socket soclose is not called. > > I am sure that the reference counting in this case is absolutely correct with > respect to managing kernel side structures. But I am not that it is correct with > respect to hiding the explicit close(2) call from other threads that may be > waiting on the socket. > In other words, I am not sure if fo_close is supposed to signify that there are no > uses of a file, or that userland close-d the file. Or perhaps these should be two > different methods. > > Additional note is that shutdown(2) doesn't wake up the thread in accept(2) > either. At least that's true for unix domain sockets. > Not sure if this is a bug. > > But the summary seems to be is that currently it is not possible to break a thread > out of accept(2) (at least without resorting to signals). I think you need to split the 'struct file' reference count into two different counts similar to the how we have vref/vrele vs vhold/vdrop for vnodes. The fget for accept and probably most other system calls should probably be equivalent to vhold, whereas things like open/dup (and storing an fd in a cmsg) should be more like vref. close() should then be a vrele(). -- John Baldwin