summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2016-06-02 22:37:34 +0200
committerAndy Wingo <wingo@pobox.com>2016-06-09 10:59:08 +0200
commite6cc051f8c3f6851be4f51ccb14109d03ae867ba (patch)
treeb2039d5c292787677ff0aa0fa60209328a1b1309
parentd8067213dc3728a37c3c60d15aa0f1113d2e8daa (diff)
downloadguile-e6cc051f8c3f6851be4f51ccb14109d03ae867ba.tar.gz
`accept' on nonblocking socket can return #f
* doc/ref/posix.texi (Network Sockets and Communication): * libguile/socket.c (scm_accept): Return #f if the socket is nonblocking and no connection is ready.
-rw-r--r--doc/ref/posix.texi25
-rw-r--r--libguile/socket.c25
2 files changed, 32 insertions, 18 deletions
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index edcff9dc2..4d2a850cf 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -3260,15 +3260,26 @@ The return value is unspecified.
@deffn {Scheme Procedure} accept sock
@deffnx {C Function} scm_accept (sock)
Accept a connection from socket port @var{sock} which has been enabled
-for listening with @code{listen} above. If there are no incoming
-connections in the queue, wait until one is available (unless
-@code{O_NONBLOCK} has been set on the socket, @pxref{Ports and File
-Descriptors,@code{fcntl}}).
+for listening with @code{listen} above.
+
+If there are no incoming connections in the queue, there are two
+possible behaviors, depending on whether @var{sock} has been configured
+for non-blocking operation or not:
+
+@itemize
+@item
+If there is no connection waiting and the socket was set to non-blocking
+mode with the @code{O_NONBLOCK} port option (@pxref{Ports and File
+Descriptors,@code{fcntl}}), return @code{#f} directly.
+
+@item
+Otherwise wait until a connection is available.
+@end itemize
The return value is a pair. The @code{car} is a new socket port,
-connected and ready to communicate. The @code{cdr} is a socket
-address object (@pxref{Network Socket Address}) which is where the
-remote connection is from (like @code{getpeername} below).
+connected and ready to communicate. The @code{cdr} is a socket address
+object (@pxref{Network Socket Address}) which is where the remote
+connection is from (like @code{getpeername} below).
All communication takes place using the new socket returned. The
given @var{sock} remains bound and listening, and @code{accept} may be
diff --git a/libguile/socket.c b/libguile/socket.c
index 1c4f2ae36..55b93572c 100644
--- a/libguile/socket.c
+++ b/libguile/socket.c
@@ -1236,16 +1236,15 @@ SCM_DEFINE (scm_make_socket_address, "make-socket-address", 2, 0, 1,
SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
(SCM sock),
- "Accept a connection on a bound, listening socket.\n"
- "If there\n"
- "are no pending connections in the queue, wait until\n"
- "one is available unless the non-blocking option has been\n"
- "set on the socket.\n\n"
- "The return value is a\n"
- "pair in which the @emph{car} is a new socket port for the\n"
- "connection and\n"
- "the @emph{cdr} is an object with address information about the\n"
- "client which initiated the connection.\n\n"
+ "Accept a connection on a bound, listening socket. If there\n"
+ "are no pending connections in the queue, there are two\n"
+ "possibilities: if the socket has been configured as\n"
+ "non-blocking, return @code{#f} directly. Otherwise wait\n"
+ "until a connection is available. When a connection comes,\n"
+ "the return value is a pair in which the @emph{car} is a new\n"
+ "socket port for the connection and the @emph{cdr} is an\n"
+ "object with address information about the client which\n"
+ "initiated the connection.\n\n"
"@var{sock} does not become part of the\n"
"connection and will continue to accept new requests.")
#define FUNC_NAME s_scm_accept
@@ -1262,7 +1261,11 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
fd = SCM_FPORT_FDES (sock);
SCM_SYSCALL (newfd = accept (fd, (struct sockaddr *) &addr, &addr_size));
if (newfd == -1)
- SCM_SYSERROR;
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return SCM_BOOL_F;
+ SCM_SYSERROR;
+ }
newsock = SCM_SOCK_FD_TO_PORT (newfd);
address = _scm_from_sockaddr (&addr, addr_size,
FUNC_NAME);