summaryrefslogtreecommitdiff
path: root/gio/gsocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'gio/gsocket.c')
-rw-r--r--gio/gsocket.c89
1 files changed, 51 insertions, 38 deletions
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 2dc005b63..22a8dd7ec 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -587,7 +587,38 @@ g_socket_details_from_fd (GSocket *socket)
socket_strerror (errsv));
}
-/* Wrapper around socket() that is shared with gnetworkmonitornetlink.c */
+static void
+socket_set_nonblock (int fd)
+{
+#ifndef G_OS_WIN32
+ GError *error = NULL;
+#else
+ gulong arg;
+#endif
+
+ /* Always use native nonblocking sockets, as Windows sets sockets to
+ * nonblocking automatically in certain operations. This way we make
+ * things work the same on all platforms.
+ */
+#ifndef G_OS_WIN32
+ if (!g_unix_set_fd_nonblocking (fd, TRUE, &error))
+ {
+ g_warning ("Error setting socket to nonblocking mode: %s", error->message);
+ g_clear_error (&error);
+ }
+#else
+ arg = TRUE;
+
+ if (ioctlsocket (fd, FIONBIO, &arg) == SOCKET_ERROR)
+ {
+ int errsv = get_socket_errno ();
+ g_warning ("Error setting socket status flags: %s", socket_strerror (errsv));
+ }
+#endif
+}
+
+/* Wrapper around socket() that is shared with gnetworkmonitornetlink.c.
+ * It always sets SOCK_CLOEXEC | SOCK_NONBLOCK. */
gint
g_socket (gint domain,
gint type,
@@ -596,13 +627,13 @@ g_socket (gint domain,
{
int fd, errsv;
-#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);
errsv = errno;
if (fd != -1)
return fd;
- /* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
+ /* It's possible that libc has SOCK_CLOEXEC and/or SOCK_NONBLOCK but the kernel does not */
if (fd < 0 && (errsv == EINVAL || errsv == EPROTOTYPE))
#endif
fd = socket (domain, type, protocol);
@@ -644,9 +675,13 @@ g_socket (gint domain,
}
#endif
+ /* Ensure the socket is non-blocking. */
+ socket_set_nonblock (fd);
+
return fd;
}
+/* Returned socket has SOCK_CLOEXEC | SOCK_NONBLOCK set. */
static gint
g_socket_create_socket (GSocketFamily family,
GSocketType type,
@@ -696,44 +731,22 @@ g_socket_constructed (GObject *object)
GSocket *socket = G_SOCKET (object);
if (socket->priv->fd >= 0)
- /* create socket->priv info from the fd */
- g_socket_details_from_fd (socket);
-
+ {
+ /* create socket->priv info from the fd and ensure it’s non-blocking */
+ g_socket_details_from_fd (socket);
+ socket_set_nonblock (socket->priv->fd);
+ }
else
- /* create the fd from socket->priv info */
- socket->priv->fd = g_socket_create_socket (socket->priv->family,
- socket->priv->type,
- socket->priv->protocol,
- &socket->priv->construct_error);
+ {
+ /* create the fd from socket->priv info; this sets it non-blocking by construction */
+ socket->priv->fd = g_socket_create_socket (socket->priv->family,
+ socket->priv->type,
+ socket->priv->protocol,
+ &socket->priv->construct_error);
+ }
if (socket->priv->fd != -1)
{
-#ifndef G_OS_WIN32
- GError *error = NULL;
-#else
- gulong arg;
-#endif
-
- /* Always use native nonblocking sockets, as Windows sets sockets to
- * nonblocking automatically in certain operations. This way we make
- * things work the same on all platforms.
- */
-#ifndef G_OS_WIN32
- if (!g_unix_set_fd_nonblocking (socket->priv->fd, TRUE, &error))
- {
- g_warning ("Error setting socket nonblocking: %s", error->message);
- g_clear_error (&error);
- }
-#else
- arg = TRUE;
-
- if (ioctlsocket (socket->priv->fd, FIONBIO, &arg) == SOCKET_ERROR)
- {
- int errsv = get_socket_errno ();
- g_warning ("Error setting socket status flags: %s", socket_strerror (errsv));
- }
-#endif
-
#ifdef SO_NOSIGPIPE
/* See note about SIGPIPE below. */
g_socket_set_option (socket, SOL_SOCKET, SO_NOSIGPIPE, TRUE, NULL);