Is it possible (and safe) to make an accepting socket non-blocking?

31,231

No idea about Windows, but the behavior you want is guaranteed by POSIX:

If the listen queue is empty of connection requests and O_NONBLOCK is not set on the file descriptor for the socket, accept() shall block until a connection is present. If the listen() queue is empty of connection requests and O_NONBLOCK is set on the file descriptor for the socket, accept() shall fail and set errno to [EAGAIN] or [EWOULDBLOCK].

Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html

Also, select or poll can be used to check for incoming connections by polling for the listening socket in the reading set.

Share:
31,231
Norswap
Author by

Norswap

Updated on March 29, 2020

Comments

  • Norswap
    Norswap about 4 years

    I'm looking for a way to interrupt an accept() call on a blocking socket. Using signals is not an option, as this is meant to be in a library and I don't want to clutter the user signals. Using select() is another option, buf for various reason it's not very appealing in my case.

    What would work well, if possible, is to set the socket to non-blocking mode (using fcntl() and O_NONBLOCK) from another thread, while the socket is blocked on an accept() call. The expected behaviour is that the accept() call will return with EAGAIN or EWOULDBLOCK in errno.

    Would it indeed work like that? Is it safe? Portable?

    If you know about the applicability of this method to Windows (where you need to use WSAIoctl() and FONBIO), I'm also interested.

  • alk
    alk over 11 years
    Are you sure an already blocking accept() would return as specified, if the file descriptor having been passed gets O_NONBLOCK set asynchronously? Your quote seems ambiguous to me for this case.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 11 years
    Oh, I misunderstood your question. No, I don't think changing the mode to non-blocking while it's already blocked is portable. Why don't you just make it nonblocking to begin with, and use poll or select prior to the accept call, and only call accept if a connection is available? There are plenty of clean ways to make select or poll return early, like the self-pipe trick.
  • Norswap
    Norswap over 11 years
    Okay, so the definite answer is that it's not up possible. Both in theory and practice (I ended up trying it out, both on Linux and Windows).
  • doron
    doron about 4 years
    On windows you should use OVERLAPPED io. For portability I would suggest using Boost Asio.
  • Norswap
    Norswap about 4 years
    Thanks for your answer, but the question was asked 8 years ago. In truth, I do not even remember what I was trying to achieve back then!
  • JamieB
    JamieB over 2 years
    On Windows (WinSock) you can actually just close the socket from another thread. This will unblock any threads blocking on that socket.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 2 years
    @JamieB: That is not a safe operation ever, and carries with it the possibility of something else being opened on the same fd number, which the accept could continue on after interruption by a signal.