Re: close(2) while accept(2) is blocked

2013-04-06 Thread John-Mark Gurney
Bakul Shah wrote this message on Sat, Mar 30, 2013 at 13:22 -0700:
> On Sat, 30 Mar 2013 09:14:34 PDT John-Mark Gurney  wrote:
> > 
> > As someone else pointed out in this thread, if a userland program
> > depends upon this behavior, it has a race condition in it...
> > 
> > Thread 1Thread 2Thread 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...
> 
> It is worse. Consider:
> 
>   fd = open(file,...);
>   read(fd, ...);
> 
> No guarantee read() gets data from the same opened file!
> Another thread could've come along, closed fd and pointed it
> to another file. So nothing is safe. Might as well stop using
> threads, right?!

Nope, you need your threads to cooperate w/ either locks or some
ownership mechanism like token passing...  As long as only one
thread own the fd, you won't have troubles...

> We are talking about cooperative threads where you don't have
> to assume the worst case.  Here not being notified on a close

Multiple people have said when threads cooperate without locks, but
no one has given a good example where they do...  The cases you list
below are IMO special (and extreme) cases...

We were talking about "cooperating" threads in a general purpose
langage like Java where you can not depend upon your other threads
doing limited amount of work...

> event can complicate things. As an example, I have done
> something like this in the past: A frontend process validating
> TCP connections and then passing on valid TCP connections to
> another process for actual service (via sendmsg() over a unix
> domain). All the worker threads in service process can do a
> recvmsg() on the same fd. They process whatever tcp connection
> they get. Now what happens when the frontend process is
> restarted for some reason?  All the worker threads need to
> eventually reconnect to a new unix domain posted by the new
> frontend process. You can handle this multiple ways but
> terminating all the blocking syscalls on the now invalid fd is
> the simplest solution from a user perspective.

This'd make an interesting race... Not sure if it could happen, but
close(), closes the receiving fd, but another thread is in the process
of receiving an fd and puts the new fd in the close of the now closed
unix domain socket...  I can draw a more detailed diagram if you want..

> > 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 you lock before close(), you have to lock before every
> other syscall on that fd. That complicates userland coding and
> slows down things when this can be handled more simply in the
> kernel.

There is "ownership" that can be passed, such as via kqueue _ONESHOT
w/ multiple threads which allows you to avoid locking and only one
thread ever owns the fd...

> Another usecase is where N worker threads all accept() on the
> same fd. Single threading using a lock defeats any performance
> gain.

In this case you still need to do something special since what happens
if one of the worker threads opens a file and/or listen/accept socket
as part of it's work?

Thread 1Thread 2Thread 3
about to call accept but
  after flag check
sets flag that close
  is going to be called
accept connect
process connection
close listen'd socket
open socket as part of
  processing gets same fd
calls listen on socket
calls accept on socket

And there we have it, a race condition...  You can't always guarantee
what your worker threads do, if you can, it's good, but we need to make
sure that beginner programs don't get into traps like these...  They
can easily make the mistake of saying, well, since close kicks all
my threads out, I'll just do that instead of making sure that they
don't have a race condition...

> > 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...
> 
> In general it just makes sens

Re: close(2) while accept(2) is blocked

2013-04-05 Thread Jilles Tjoelker
On Thu, Apr 04, 2013 at 08:43:17PM +0300, Andriy Gapon wrote:
> on 01/04/2013 18:22 John Baldwin said the following:
> > 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().

> This model makes perfect sense.
> Unfortunately, ENOTIME to work on this.

This looks like it can work but I don't know whether it's worth the
trouble.

> Meanwhile I am using the following patch specific to local domain
> sockets, accept(2) and shutdown(2).  Turns out that the problematic
> application does both shutdown(RDWR) and close(2), but that doesn't
> help on FreeBSD.
> BTW, this is the application:
> http://thread.gmane.org/gmane.os.freebsd.devel.office/1754
> The patch does help.

> Author: Andriy Gapon 
> Date:   Thu Mar 28 20:08:13 2013 +0200
> 
> [test!] uipc_shutdown: use soisdisconnected instead of socantsendmore
> 
> So that in addition to disabling sends we also wake up threads blocked
> in accept (on so_timeo in general).
> 
> diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
> index 9b60eab..e93d46c 100644
> --- a/sys/kern/uipc_usrreq.c
> +++ b/sys/kern/uipc_usrreq.c
> @@ -1074,7 +1074,7 @@ uipc_shutdown(struct socket *so)
> 
>   UNP_LINK_WLOCK();
>   UNP_PCB_LOCK(unp);
> - socantsendmore(so);
> + soisdisconnected(so);
>   unp_shutdown(unp);
>   UNP_PCB_UNLOCK(unp);
>   UNP_LINK_WUNLOCK();

I think this patch makes shutdown(SHUT_WR) on unix domain sockets act
like shutdown(SHUT_RDWR), i.e. receives are incorrectly denied.

The below patch also makes shutdown(SHUT_RDWR) abort a blocking accept
on a unix domain socket, but it should work for all domains:

Index: sys/kern/uipc_socket.c
===
--- sys/kern/uipc_socket.c  (revision 248873)
+++ sys/kern/uipc_socket.c  (working copy)
@@ -2428,9 +2428,11 @@ soshutdown(struct socket *so, int how)
sorflush(so);
if (how != SHUT_RD) {
error = (*pr->pr_usrreqs->pru_shutdown)(so);
+   wakeup(&so->so_timeo);
CURVNET_RESTORE();
return (error);
}
+   wakeup(&so->so_timeo);
CURVNET_RESTORE();
return (0);
 }

A blocking accept (and some other operations) is waiting on
&so->so_timeo. Once it wakes up, it will detect the SBS_CANTRCVMORE bit.

A spurious wakeup on so->so_timeo appears harmless (sleep retried)
except when lingering on close (SO_LINGER) so this should be fairly
safe.

-- 
Jilles Tjoelker
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-04-04 Thread Andriy Gapon
on 01/04/2013 18:22 John Baldwin said the following:
> 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().

This model makes perfect sense.
Unfortunately, ENOTIME to work on this.

Meanwhile I am using the following patch specific to local domain sockets,
accept(2) and shutdown(2).  Turns out that the problematic application does both
shutdown(RDWR) and close(2), but that doesn't help on FreeBSD.
BTW, this is the application:
http://thread.gmane.org/gmane.os.freebsd.devel.office/1754
The patch does help.

Author: Andriy Gapon 
Date:   Thu Mar 28 20:08:13 2013 +0200

[test!] uipc_shutdown: use soisdisconnected instead of socantsendmore

So that in addition to disabling sends we also wake up threads blocked
in accept (on so_timeo in general).

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 9b60eab..e93d46c 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1074,7 +1074,7 @@ uipc_shutdown(struct socket *so)

UNP_LINK_WLOCK();
UNP_PCB_LOCK(unp);
-   socantsendmore(so);
+   soisdisconnected(so);
unp_shutdown(unp);
UNP_PCB_UNLOCK(unp);
UNP_LINK_WUNLOCK();


-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-04-04 Thread Andriy Gapon
on 30/03/2013 18:14 John-Mark Gurney said the following:
> 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 2Thread 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..
> 

I wish to abstract as much as possible from how an application may use, misuse 
or
even abuse the close+ interaction.  But I think that the behavior that
provides more information / capabilities is preferable over the behavior that 
does
not.  E.g. your example above does not apply to a utility that has only two
threads.  The "three threads" problem can also be solved if all the threads
cooperate.  But as I've said.

-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-04-01 Thread John Baldwin
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
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-30 Thread Bakul Shah
On Sat, 30 Mar 2013 09:14:34 PDT John-Mark Gurney  wrote:
> 
> 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 2Thread 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...

It is worse. Consider:

fd = open(file,...);
read(fd, ...);

No guarantee read() gets data from the same opened file!
Another thread could've come along, closed fd and pointed it
to another file. So nothing is safe. Might as well stop using
threads, right?!

We are talking about cooperative threads where you don't have
to assume the worst case.  Here not being notified on a close
event can complicate things. As an example, I have done
something like this in the past: A frontend process validating
TCP connections and then passing on valid TCP connections to
another process for actual service (via sendmsg() over a unix
domain). All the worker threads in service process can do a
recvmsg() on the same fd. They process whatever tcp connection
they get. Now what happens when the frontend process is
restarted for some reason?  All the worker threads need to
eventually reconnect to a new unix domain posted by the new
frontend process. You can handle this multiple ways but
terminating all the blocking syscalls on the now invalid fd is
the simplest solution from a user perspective.

> 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 you lock before close(), you have to lock before every
other syscall on that fd. That complicates userland coding and
slows down things when this can be handled more simply in the
kernel.

Another usecase is where N worker threads all accept() on the
same fd. Single threading using a lock defeats any performance
gain.

> 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...

In general it just makes sense to notify everyone waiting on
something that the situation has changed and they are going to
have to wait forever.  The kernel should already have the
necessary information about which threads are sleeping on a
fd. Wake them all up. On being awakened they see that the fd
is no longer valid and all return with a count of data already
read or -1 and EBADF. Doing the equivalent in userland is
complicated.

Carl has pointed out how BSD and Linux have required a
workaround compared to Solaris and OS X (in Java and IIRC, the
Go runtime). Seems like we have a number of usecases and this
is something worth fixing.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-30 Thread Mark
> 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 2Thread 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...

Right. The only "safe" way is to have all blocking syscalls on the
same fd in the same process return to userland. This would need to be
initiated in the close() syscall.

Btw. Threads aren't the only scenario. A signal handler can also close
the fd. Maybe not advised, but I have used this "technique" to force a
return from a blocking accept() call since about FBSD4.x


Mark.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-30 Thread John-Mark Gurney
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  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 1Thread 2Thread 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."
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-29 Thread Bakul Shah
On Fri, 29 Mar 2013 14:30:59 PDT Carl Shapiro  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.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-29 Thread Carl Shapiro
On Thu, Mar 28, 2013 at 9:54 AM, Andriy Gapon  wrote:

> 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).
>

This is a known problem for Java.  Closing a socket that another thread is
block on is supposed to unblock a thread and throw a SocketException.

http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#close()

In other operating systems, such as Solaris and MacOS X, closing the
descriptor causes blocked system calls to return with an error.

FreeBSD (and Linux) do not behave this way.  There, a JVM must do extra
bookkeeping to associate file descriptors with threads blocked on the
descriptor.  This allows the close method to identify blocked threads and
send them a signal.  On those threads the caller of the blocking method
must further distinguish an error return as being caused by a signal sent
on behalf of close.

It is not obvious whether there is any benefit to having the current
blocking behaviour.  Threads are an afterthought in UNIX so this could just
be an oversight.  It would make a high-level language runtimes simpler if
FreeBSD behaved more like Solaris and MacOS X.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: close(2) while accept(2) is blocked

2013-03-28 Thread Jilles Tjoelker
On Thu, Mar 28, 2013 at 06:54:31PM +0200, 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.

I agree this is expected and correct from the kernel point of view.

> 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.

It would be possible to keep track of the file descriptor number but I
think it is not worth the large amount of extra code.

Keeping track of file descriptor number would be necessary to interrupt
waits after a close or dup2 on the file descriptor that was passed to
the blocking call, even if the object remains open on a different file
descriptor number or in a different process.

Also, most people would use the new functionality incorrectly anyway. A
close() on a file descriptor another thread is using is risky since it
is in most cases impossible to prove that the other thread is in fact
blocked on the file descriptor and not preempted right before making the
system call. In the latter case, the other thread might accept a
connection from a different socket created later. A dup2() of /dev/null
onto the file descriptor would be safer.

> 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.

I think it is a bug. It works properly for IPv4 TCP sockets.

The resulting error is [ECONNABORTED] for a blocking socket which likely
leads to infinite looping if the thread does not know about the
shutdown(2) (because that error normally means the accept should be
retried later). For a non-blocking socket the error is [EWOULDBLOCK]
which also leads to infinite looping and is certainly wrong because
select/poll do report the socket as readable. Both of these are in
kern_accept() in sys/kern/uipc_syscalls.c.

POSIX does not say which error code we should return here but these two
are almost certainly wrong (it is usable for waking up threads stuck in
accept() if those threads check a variable after every accept() failure
and do not rely on the exact value of errno). Linux returns [EINVAL] for
both blocking and non-blocking sockets, probably from the POSIX error
condition "The socket is not accepting connections." In our man page
that error condition is formulated "listen(2) has not been called on the
socket descriptor." which is clearly not the case.

Also, I think a non-blocking accept() should immediately fail with the
head->so_error if it is set, rather than returning [EWOULDBLOCK] until
another connection arrives. Likewise, filt_solisten() in
sys/kern/uipc_socket.c only returns true if there is a connection, not
if there was an error or shutdown() has been called. On the other hand,
sopoll_generic() looks correct.

Error reporting on non-blocking accept() might usefully be postponed
until there is a connection or the socket has been shut down, to reduce
context switches.

> 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).

Pthread cancellation works better than raw signals for this use case. In
a proper implementation such as in FreeBSD 9.0 or newer and used
properly, it allows avoiding the resource leak that may happen when
calling longjmp() or pthread_exit() in a signal handler just after
accept() has created a new socket.

-- 
Jilles Tjoelker
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"