diff options
author | Pekka Paalanen <ppaalanen@gmail.com> | 2012-03-21 11:11:26 +0200 |
---|---|---|
committer | Pekka Paalanen <ppaalanen@gmail.com> | 2012-04-20 16:26:37 +0300 |
commit | 7134a439c1a028cad51a5160f56c84a961be9f72 (patch) | |
tree | 0d9ec2a744e6b68035db9a37ceea3566b62baa96 /src | |
parent | da6b1a8e4774234c2dbdd9f2875de21b41086d00 (diff) |
os: wrap socket(SOCK_CLOEXEC) calls
Some system C libraries do not offer SOCK_CLOEXEC flag.
Add a new header for OS compatibility wrappers. Wrap socket() calls into
wl_os_socket_cloexec() which makes sure the O_CLOEXEC flag gets set on
the file descriptor.
On systems having SOCK_CLOEXEC this uses the old socket() call, and
falls back if it fails due to the flag (kernel not supporting it).
wayland-os.h is private and not exported.
Add close-on-exec tests for both normal and forced fallback paths.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/wayland-client.c | 3 | ||||
-rw-r--r-- | src/wayland-os.c | 69 | ||||
-rw-r--r-- | src/wayland-os.h | 29 | ||||
-rw-r--r-- | src/wayland-server.c | 3 |
5 files changed, 104 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7217236..c685885 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,8 @@ libwayland_util_la_SOURCES = \ connection.c \ wayland-util.c \ wayland-util.h \ + wayland-os.c \ + wayland-os.h \ wayland-private.h libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt diff --git a/src/wayland-client.c b/src/wayland-client.c index 713c894..794f716 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -36,6 +36,7 @@ #include <sys/poll.h> #include "wayland-util.h" +#include "wayland-os.h" #include "wayland-client.h" #include "wayland-private.h" @@ -307,7 +308,7 @@ connect_to_socket(struct wl_display *display, const char *name) const char *runtime_dir; size_t name_size; - display->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + display->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); if (display->fd < 0) return -1; diff --git a/src/wayland-os.c b/src/wayland-os.c new file mode 100644 index 0000000..5ff4391 --- /dev/null +++ b/src/wayland-os.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include "wayland-os.h" + +static int +set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + +err: + close(fd); + return -1; +} + +int +wl_os_socket_cloexec(int domain, int type, int protocol) +{ + int fd; + +#ifdef SOCK_CLOEXEC + errno = 0; + fd = socket(domain, type | SOCK_CLOEXEC, protocol); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = socket(domain, type, protocol); + return set_cloexec_or_close(fd); +} diff --git a/src/wayland-os.h b/src/wayland-os.h new file mode 100644 index 0000000..49adc2b --- /dev/null +++ b/src/wayland-os.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef WAYLAND_OS_H +#define WAYLAND_OS_H + +int +wl_os_socket_cloexec(int domain, int type, int protocol); + +#endif diff --git a/src/wayland-server.c b/src/wayland-server.c index 8ca27bd..1fe00a9 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -44,6 +44,7 @@ #include "wayland-private.h" #include "wayland-server.h" #include "wayland-server-protocol.h" +#include "wayland-os.h" struct wl_socket { int fd; @@ -970,7 +971,7 @@ wl_display_add_socket(struct wl_display *display, const char *name) if (s == NULL) return -1; - s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); if (s->fd < 0) { free(s); return -1; |