aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-11-08 22:11:35 +0100
committerMax Kellermann <max@duempel.org>2009-11-08 22:11:35 +0100
commitf66edccffdc4a9276ae9dced69fa6fb74ee1f97e (patch)
tree3350b0852762cb393c12054e28c999532b4fd027
parentb043ade456818a414c726c8525bb8ec63658edc8 (diff)
downloadmpd-f66edccffdc4a9276ae9dced69fa6fb74ee1f97e.tar.gz
mpd-f66edccffdc4a9276ae9dced69fa6fb74ee1f97e.tar.xz
mpd-f66edccffdc4a9276ae9dced69fa6fb74ee1f97e.zip
fd_util: added O_NONBLOCK functions
Changed the wrappers for pipe(), socket(), accept(). On WIN32, this does not work for pipe().
-rw-r--r--src/event_pipe.c7
-rw-r--r--src/fd_util.c45
-rw-r--r--src/fd_util.h18
-rw-r--r--src/listen.c6
-rw-r--r--src/output/httpd_output_plugin.c3
-rw-r--r--src/socket_util.c2
6 files changed, 55 insertions, 26 deletions
diff --git a/src/event_pipe.c b/src/event_pipe.c
index 17e11097a..4b7e741ff 100644
--- a/src/event_pipe.c
+++ b/src/event_pipe.c
@@ -18,7 +18,6 @@
*/
#include "event_pipe.h"
-#include "utils.h"
#include "fd_util.h"
#include <stdbool.h>
@@ -85,13 +84,9 @@ void event_pipe_init(void)
GIOChannel *channel;
int ret;
- ret = pipe_cloexec(event_pipe);
+ ret = pipe_cloexec_nonblock(event_pipe);
if (ret < 0)
g_error("Couldn't open pipe: %s", strerror(errno));
-#ifndef WIN32
- if (set_nonblocking(event_pipe[1]) < 0)
- g_error("Couldn't set non-blocking I/O: %s", strerror(errno));
-#endif
channel = g_io_channel_unix_new(event_pipe[0]);
event_pipe_source_id = g_io_add_watch(channel, G_IO_IN,
diff --git a/src/fd_util.c b/src/fd_util.c
index a8be69be7..2350596c4 100644
--- a/src/fd_util.c
+++ b/src/fd_util.c
@@ -68,6 +68,29 @@ fd_set_cloexec(int fd, bool enable)
#endif
}
+/**
+ * Enables non-blocking mode for the specified file descriptor. On
+ * WIN32, this function only works for sockets.
+ */
+static int
+fd_set_nonblock(int fd)
+{
+#ifdef WIN32
+ u_long val = 1;
+ return ioctlsocket(fd, FIONBIO, &val);
+#else
+ int flags;
+
+ assert(fd >= 0);
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return flags;
+
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+#endif
+}
+
int
open_cloexec(const char *path_fs, int flags)
{
@@ -108,7 +131,7 @@ creat_cloexec(const char *path_fs, int mode)
}
int
-pipe_cloexec(int fd[2])
+pipe_cloexec_nonblock(int fd[2])
{
#ifdef WIN32
return _pipe(event_pipe, 512, _O_BINARY);
@@ -116,7 +139,7 @@ pipe_cloexec(int fd[2])
int ret;
#ifdef HAVE_PIPE2
- ret = pipe2(fd, O_CLOEXEC);
+ ret = pipe2(fd, O_CLOEXEC|O_NONBLOCK);
if (ret >= 0 || errno != ENOSYS)
return ret;
#endif
@@ -125,6 +148,11 @@ pipe_cloexec(int fd[2])
if (ret >= 0) {
fd_set_cloexec(fd[0], true);
fd_set_cloexec(fd[1], true);
+
+#ifndef WIN32
+ fd_set_nonblock(fd[0]);
+ fd_set_nonblock(fd[1]);
+#endif
}
return ret;
@@ -132,12 +160,12 @@ pipe_cloexec(int fd[2])
}
int
-socket_cloexec(int domain, int type, int protocol)
+socket_cloexec_nonblock(int domain, int type, int protocol)
{
int fd;
-#ifdef SOCK_CLOEXEC
- fd = socket(domain, type | SOCK_CLOEXEC, protocol);
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ fd = socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
if (fd >= 0 || errno != EINVAL)
return fd;
#endif
@@ -150,13 +178,15 @@ socket_cloexec(int domain, int type, int protocol)
}
int
-accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r)
+accept_cloexec_nonblock(int fd, struct sockaddr *address,
+ size_t *address_length_r)
{
int ret;
socklen_t address_length = *address_length_r;
#ifdef HAVE_ACCEPT4
- ret = accept4(fd, address, &address_length, SOCK_CLOEXEC);
+ ret = accept4(fd, address, &address_length,
+ SOCK_CLOEXEC|SOCK_NONBLOCK);
if (ret >= 0 || errno != ENOSYS) {
if (ret >= 0)
*address_length_r = address_length;
@@ -168,6 +198,7 @@ accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r)
ret = accept(fd, address, &address_length);
if (ret >= 0) {
fd_set_cloexec(ret, true);
+ fd_set_nonblock(ret);
*address_length_r = address_length;
}
diff --git a/src/fd_util.h b/src/fd_util.h
index 2dfc151f2..d9e811d51 100644
--- a/src/fd_util.h
+++ b/src/fd_util.h
@@ -49,23 +49,27 @@ creat_cloexec(const char *path_fs, int mode);
/**
* Wrapper for pipe(), which sets the CLOEXEC flag (atomically if
* supported by the OS).
+ *
+ * On systems that supports it (everybody except for Windows), it also
+ * sets the NONBLOCK flag.
*/
int
-pipe_cloexec(int fd[2]);
+pipe_cloexec_nonblock(int fd[2]);
/**
- * Wrapper for socket(), which sets the CLOEXEC flag (atomically if
- * supported by the OS).
+ * Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag
+ * (atomically if supported by the OS).
*/
int
-socket_cloexec(int domain, int type, int protocol);
+socket_cloexec_nonblock(int domain, int type, int protocol);
/**
- * Wrapper for accept(), which sets the CLOEXEC flag (atomically if
- * supported by the OS).
+ * Wrapper for accept(), which sets the CLOEXEC and the NONBLOCK flags
+ * (atomically if supported by the OS).
*/
int
-accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r);
+accept_cloexec_nonblock(int fd, struct sockaddr *address,
+ size_t *address_length_r);
/**
* Wrapper for inotify_init(), which sets the CLOEXEC flag (atomically
diff --git a/src/listen.c b/src/listen.c
index 2490780ad..668a8077c 100644
--- a/src/listen.c
+++ b/src/listen.c
@@ -21,7 +21,6 @@
#include "socket_util.h"
#include "client.h"
#include "conf.h"
-#include "utils.h"
#include "fd_util.h"
#include "config.h"
@@ -429,10 +428,9 @@ listen_in_event(G_GNUC_UNUSED GIOChannel *source,
struct sockaddr_storage sa;
size_t sa_length = sizeof(sa);
- fd = accept_cloexec(listen_fd, (struct sockaddr*)&sa, &sa_length);
+ fd = accept_cloexec_nonblock(listen_fd, (struct sockaddr*)&sa,
+ &sa_length);
if (fd >= 0) {
- set_nonblocking(fd);
-
client_new(fd, (struct sockaddr*)&sa, sa_length,
get_remote_uid(fd));
} else if (fd < 0 && errno != EINTR) {
diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c
index 6d5e99c57..53bcc2deb 100644
--- a/src/output/httpd_output_plugin.c
+++ b/src/output/httpd_output_plugin.c
@@ -195,7 +195,8 @@ httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
/* the listener socket has become readable - a client has
connected */
- fd = accept_cloexec(httpd->fd, (struct sockaddr*)&sa, &sa_length);
+ fd = accept_cloexec_nonblock(httpd->fd, (struct sockaddr*)&sa,
+ &sa_length);
if (fd >= 0) {
/* can we allow additional client */
if (httpd->open &&
diff --git a/src/socket_util.c b/src/socket_util.c
index edbc67d12..e737fdf06 100644
--- a/src/socket_util.c
+++ b/src/socket_util.c
@@ -103,7 +103,7 @@ socket_bind_listen(int domain, int type, int protocol,
int passcred = 1;
#endif
- fd = socket_cloexec(domain, type, protocol);
+ fd = socket_cloexec_nonblock(domain, type, protocol);
if (fd < 0) {
g_set_error(error, listen_quark(), errno,
"Failed to create socket: %s", g_strerror(errno));