Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 Mar 2013 09:14:34 -0700
From:      John-Mark Gurney <jmg@funkthat.com>
To:        Bakul Shah <bakul@bitblocks.com>
Cc:        freebsd-net@freebsd.org, Carl Shapiro <carl.shapiro@gmail.com>, Andriy Gapon <avg@freebsd.org>, FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: close(2) while accept(2) is blocked
Message-ID:  <20130330161434.GG76354@funkthat.com>
In-Reply-To: <20130329235431.32D7FB82A@mail.bitblocks.com>
References:  <515475C7.6010404@FreeBSD.org> <CANVK_QgnC-pLGwh7Oad87JO_z1WmLeY3kfT9HhdpSzMnpjdNgA@mail.gmail.com> <20130329235431.32D7FB82A@mail.bitblocks.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Bakul Shah wrote this message on Fri, Mar 29, 2013 at 16:54 -0700:
> On Fri, 29 Mar 2013 14:30:59 PDT Carl Shapiro <carl.shapiro@gmail.com> wrote:
> > 
> > In other operating systems, such as Solaris and MacOS X, closing the
> > descriptor causes blocked system calls to return with an error.
> 
> What happens if you select() on a socket and another thread
> closes this socket?  Ideally select() should return (with
> EINTR?) so that the blocking thread can some cleanup action.
> And if you do that, the blocking accept() case is not really
> different.
> 
> There is no point in *not* telling blocking threads that the
> descriptor they're waiting on is one EBADF and nothing is
> going to happen.
> 
> > It is not obvious whether there is any benefit to having the current
> > blocking behaviour. 
> 
> This may need some new kernel code but IMHO this is worth fixing.

As someone else pointed out in this thread, if a userland program
depends upon this behavior, it has a race condition in it...

Thread 1		Thread 2		Thread 3
						enters routine to read
enters routine to close
calls close(3)
			open() returns 3
						does read(3) for orignal fd

How can the original threaded program ensure that thread 2 doesn't
create a new fd in between?  So even if you use a lock, this won't
help, because as far as I know, there is no enter read and unlock
mutex call yet...

I decided long ago that this is only solvable by proper use of locking
and ensuring that if you call close (the syscall), that you do not have
any other thread that may use the fd.  It's the close routine's (not
syscall) function to make sure it locks out other threads and all other
are out of the code path that will use the fd before it calls close..

If someone could describe how this new eject a person from read could
be done in a race safe way, then I'd say go ahead w/ it...  Otherwise
we're just moving the race around, and letting people think that they
have solved the problem when they haven't...

I think I remeber another thread about this from a year or two ago,
but I couldn't find it...  If someone finds it, posting a link would
be nice..

-- 
  John-Mark Gurney				Voice: +1 415 225 5579

     "All that I will do, has been done, All that I have, has not."



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130330161434.GG76354>