#include "gsocket.h"
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
+
#include <errno.h>
#include <signal.h>
#include <string.h>
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;
/* 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
* 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
*/
* 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
*/
*
* 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
*/
* 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
*/
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)
{
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)
{
/* 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))
{