GSocket: Use MSG_CMSG_CLOEXEC
[platform/upstream/glib.git] / gio / gsocket.c
index ad0d940..97120a6 100644 (file)
 
 #include "gsocket.h"
 
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
+
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
@@ -50,6 +54,7 @@
 #include "gioerror.h"
 #include "gioenums.h"
 #include "gioerror.h"
+#include "gio-marshal.h"
 #include "gnetworkingprivate.h"
 #include "gsocketaddress.h"
 #include "gsocketcontrolmessage.h"
@@ -239,22 +244,17 @@ static void
 set_fd_nonblocking (int fd)
 {
 #ifndef G_OS_WIN32
-  glong arg;
+  GError *error = NULL;
 #else
   gulong arg;
 #endif
 
 #ifndef G_OS_WIN32
-  if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
+  if (!g_unix_set_fd_nonblocking (fd, TRUE, &error))
     {
-      g_warning ("Error getting socket status flags: %s", socket_strerror (errno));
-      arg = 0;
+      g_warning ("Error setting socket nonblocking: %s", error->message);
+      g_clear_error (&error);
     }
-
-  arg = arg | O_NONBLOCK;
-
-  if (fcntl (fd, F_SETFL, arg) < 0)
-      g_warning ("Error setting socket status flags: %s", socket_strerror (errno));
 #else
   arg = TRUE;
 
@@ -677,6 +677,7 @@ g_socket_class_init (GSocketClass *klass)
 
   /* Make sure winsock has been initialized */
   type = g_inet_address_get_type ();
+  (type); /* To avoid -Wunused-but-set-variable */
 
 #ifdef SIGPIPE
   /* There is no portable, thread-safe way to avoid having the process
@@ -1478,7 +1479,7 @@ g_socket_speaks_ipv4 (GSocket *socket)
 /**
  * g_socket_accept:
  * @socket: a #GSocket.
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Accept incoming connections on a connection-based socket. This removes
@@ -1590,7 +1591,7 @@ g_socket_accept (GSocket       *socket,
  * g_socket_connect:
  * @socket: a #GSocket.
  * @address: a #GSocketAddress specifying the remote address.
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Connect the socket to the specified remote address.
@@ -1736,7 +1737,7 @@ g_socket_check_connect_result (GSocket  *socket,
  * @buffer: a buffer to read data into (which should be at least @size
  *     bytes long).
  * @size: the number of bytes you want to read from the socket
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Receive data (up to @size bytes) from a socket. This is mainly used by
@@ -1754,15 +1755,17 @@ g_socket_check_connect_result (GSocket  *socket,
  * received, the additional data will be returned in future calls to
  * g_socket_receive().
  *
- * If the socket is in blocking mode the call will block until there is
- * some data to receive or there is an error. If there is no data available
- * and the socket is in non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error
- * will be returned. To be notified when data is available, wait for the
+ * If the socket is in blocking mode the call will block until there
+ * is some data to receive, the connection is closed, or there is an
+ * error. If there is no data available and the socket is in
+ * non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error will be
+ * returned. To be notified when data is available, wait for the
  * %G_IO_IN condition.
  *
  * On error -1 is returned and @error is set accordingly.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
  *
  * Since: 2.22
  */
@@ -1785,14 +1788,15 @@ g_socket_receive (GSocket       *socket,
  *     bytes long).
  * @size: the number of bytes you want to read from the socket
  * @blocking: whether to do blocking or non-blocking I/O
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * This behaves exactly the same as g_socket_receive(), except that
  * the choice of blocking or non-blocking behavior is determined by
  * the @blocking argument rather than by @socket's properties.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
  *
  * Since: 2.26
  */
@@ -1863,7 +1867,7 @@ g_socket_receive_with_blocking (GSocket       *socket,
  * @buffer: a buffer to read data into (which should be at least @size
  *     bytes long).
  * @size: the number of bytes you want to read from the socket
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Receive data (up to @size bytes) from a socket.
@@ -1874,7 +1878,8 @@ g_socket_receive_with_blocking (GSocket       *socket,
  *
  * See g_socket_receive() for additional information.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
  *
  * Since: 2.22
  */
@@ -1912,9 +1917,9 @@ g_socket_receive_from (GSocket         *socket,
 /**
  * g_socket_send:
  * @socket: a #GSocket
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
  * @size: the number of bytes to send
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Tries to send @size bytes from @buffer on the socket. This is
@@ -1952,10 +1957,10 @@ g_socket_send (GSocket       *socket,
 /**
  * g_socket_send_with_blocking:
  * @socket: a #GSocket
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
  * @size: the number of bytes to send
  * @blocking: whether to do blocking or non-blocking I/O
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * This behaves exactly the same as g_socket_send(), except that
@@ -2031,9 +2036,9 @@ g_socket_send_with_blocking (GSocket       *socket,
  * g_socket_send_to:
  * @socket: a #GSocket
  * @address: a #GSocketAddress, or %NULL
- * @buffer: the buffer containing the data to send.
+ * @buffer: (array length=size): the buffer containing the data to send.
  * @size: the number of bytes to send
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Tries to send @size bytes from @buffer to @address. If @address is
@@ -2467,6 +2472,10 @@ socket_source_dispatch (GSource     *source,
   GSocketSourceFunc func = (GSocketSourceFunc)callback;
   GSocketSource *socket_source = (GSocketSource *)source;
 
+#ifdef G_OS_WIN32
+  socket_source->pollfd.revents = update_condition (socket_source->socket);
+#endif
+
   return (*func) (socket_source->socket,
                  socket_source->pollfd.revents & socket_source->condition,
                  user_data);
@@ -2493,12 +2502,42 @@ socket_source_finalize (GSource *source)
     }
 }
 
+static gboolean
+socket_source_closure_callback (GSocket      *socket,
+                               GIOCondition  condition,
+                               gpointer      data)
+{
+  GClosure *closure = data;
+
+  GValue params[2] = { { 0, }, { 0, } };
+  GValue result_value = { 0, };
+  gboolean result;
+
+  g_value_init (&result_value, G_TYPE_BOOLEAN);
+
+  g_value_init (&params[0], G_TYPE_SOCKET);
+  g_value_set_object (&params[0], socket);
+  g_value_init (&params[1], G_TYPE_IO_CONDITION);
+  g_value_set_flags (&params[1], condition);
+
+  g_closure_invoke (closure, &result_value, 2, params, NULL);
+
+  result = g_value_get_boolean (&result_value);
+  g_value_unset (&result_value);
+  g_value_unset (&params[0]);
+  g_value_unset (&params[1]);
+
+  return result;
+}
+
 static GSourceFuncs socket_source_funcs =
 {
   socket_source_prepare,
   socket_source_check,
   socket_source_dispatch,
-  socket_source_finalize
+  socket_source_finalize,
+  (GSourceFunc)socket_source_closure_callback,
+  (GSourceDummyMarshal)_gio_marshal_BOOLEAN__FLAGS,
 };
 
 static GSource *
@@ -2557,10 +2596,10 @@ socket_source_new (GSocket      *socket,
 }
 
 /**
- * g_socket_create_source:
+ * g_socket_create_source: (skip)
  * @socket: a #GSocket
  * @condition: a #GIOCondition mask to monitor
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  *
  * Creates a %GSource that can be attached to a %GMainContext to monitor
  * for the availibility of the specified @condition on the socket.
@@ -2661,7 +2700,7 @@ g_socket_condition_check (GSocket      *socket,
  * g_socket_condition_wait:
  * @socket: a #GSocket
  * @condition: a #GIOCondition mask to wait for
- * @cancellable: a #GCancellable, or %NULL
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
  * @error: a #GError pointer, or %NULL
  *
  * Waits for @condition to become true on @socket. When the condition
@@ -2788,13 +2827,13 @@ g_socket_condition_wait (GSocket       *socket,
  * g_socket_send_message:
  * @socket: a #GSocket
  * @address: a #GSocketAddress, or %NULL
- * @vectors: an array of #GOutputVector structs
+ * @vectors: (array length=num_vectors): an array of #GOutputVector structs
  * @num_vectors: the number of elements in @vectors, or -1
- * @messages: a pointer to an array of #GSocketControlMessages, or
- *   %NULL.
+ * @messages: (array length=num_messages) (allow-none): a pointer to an
+ *   array of #GSocketControlMessages, or %NULL.
  * @num_messages: number of elements in @messages, or -1.
  * @flags: an int containing #GSocketMsgFlags flags
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: #GError for error reporting, or %NULL to ignore.
  *
  * Send data to @address on @socket.  This is the most complicated and
@@ -3086,14 +3125,14 @@ g_socket_send_message (GSocket                *socket,
  * g_socket_receive_message:
  * @socket: a #GSocket
  * @address: a pointer to a #GSocketAddress pointer, or %NULL
- * @vectors: an array of #GInputVector structs
+ * @vectors: (array length=num_vectors): an array of #GInputVector structs
  * @num_vectors: the number of elements in @vectors, or -1
- * @messages: a pointer which may be filled with an array of
- *     #GSocketControlMessages, or %NULL
+ * @messages: (array length=num_messages) (allow-none): a pointer which
+ *    may be filled with an array of #GSocketControlMessages, or %NULL
  * @num_messages: a pointer which will be filled with the number of
  *    elements in @messages, or %NULL
  * @flags: a pointer to an int containing #GSocketMsgFlags flags
- * @cancellable: a %GCancellable or %NULL
+ * @cancellable: (allow-none): a %GCancellable or %NULL
  * @error: a #GError pointer, or %NULL
  *
  * Receive data from a socket.  This is the most complicated and
@@ -3146,14 +3185,16 @@ g_socket_send_message (GSocket                *socket,
  * sufficiently-large buffer.
  *
  * If the socket is in blocking mode the call will block until there
- * is some data to receive or there is an error. If there is no data
- * available and the socket is in non-blocking mode, a
- * %G_IO_ERROR_WOULD_BLOCK error will be returned. To be notified when
- * data is available, wait for the %G_IO_IN condition.
+ * is some data to receive, the connection is closed, or there is an
+ * error. If there is no data available and the socket is in
+ * non-blocking mode, a %G_IO_ERROR_WOULD_BLOCK error will be
+ * returned. To be notified when data is available, wait for the
+ * %G_IO_IN condition.
  *
  * On error -1 is returned and @error is set accordingly.
  *
- * Returns: Number of bytes read, or -1 on error
+ * Returns: Number of bytes read, or 0 if the connection was closed by
+ * the peer, or -1 on error
  *
  * Since: 2.22
  */
@@ -3249,6 +3290,14 @@ g_socket_receive_message (GSocket                 *socket,
     else
       msg.msg_flags = 0;
 
+    /* We always set the close-on-exec flag so we don't leak file
+     * descriptors into child processes.  Note that gunixfdmessage.c
+     * will later call fcntl (fd, FD_CLOEXEC), but that isn't atomic.
+     */
+#ifdef MSG_CMSG_CLOEXEC
+    msg.msg_flags |= MSG_CMSG_CLOEXEC;
+#endif
+
     /* do it */
     while (1)
       {
@@ -3258,6 +3307,14 @@ g_socket_receive_message (GSocket                 *socket,
          return -1;
 
        result = recvmsg (socket->priv->fd, &msg, msg.msg_flags);
+#ifdef MSG_CMSG_CLOEXEC        
+       if (result < 0 && get_socket_errno () == EINVAL)
+         {
+           /* We must be running on an old kernel.  Call without the flag. */
+           msg.msg_flags &= ~(MSG_CMSG_CLOEXEC);
+           result = recvmsg (socket->priv->fd, &msg, msg.msg_flags);
+         }
+#endif
 
        if (result < 0)
          {
@@ -3293,12 +3350,7 @@ g_socket_receive_message (GSocket                 *socket,
     /* decode control messages */
     {
       GPtrArray *my_messages = NULL;
-      const gchar *scm_pointer;
       struct cmsghdr *cmsg;
-      gsize scm_size;
-
-      scm_pointer = (const gchar *) msg.msg_control;
-      scm_size = msg.msg_controllen;
 
       for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
        {