g_unix_set_fd_nonblocking: New API to control file descriptor blocking state

And use it in relevant places in GLib.

https://bugzilla.gnome.org/show_bug.cgi?id=649225
This commit is contained in:
Colin Walters 2011-05-03 09:52:10 -04:00
parent e08e70e08d
commit ed37970a04
6 changed files with 69 additions and 32 deletions

View File

@ -21,11 +21,10 @@
*/
#include "config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include "glib.h"
#ifdef G_OS_UNIX
#include "glib-unix.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <gioerror.h>
#ifdef G_OS_WIN32
#include <windows.h>
@ -193,22 +192,6 @@ g_cancellable_class_init (GCancellableClass *klass)
}
#ifndef G_OS_WIN32
static void
set_fd_nonblocking (int fd)
{
#ifdef F_GETFL
glong fcntl_flags;
fcntl_flags = fcntl (fd, F_GETFL);
#ifdef O_NONBLOCK
fcntl_flags |= O_NONBLOCK;
#else
fcntl_flags |= O_NDELAY;
#endif
fcntl (fd, F_SETFL, fcntl_flags);
#endif
}
static void
set_fd_close_exec (int fd)
@ -235,8 +218,8 @@ g_cancellable_open_pipe (GCancellable *cancellable)
/* Make them nonblocking, just to be sure we don't block
* on errors and stuff
*/
set_fd_nonblocking (priv->cancel_pipe[0]);
set_fd_nonblocking (priv->cancel_pipe[1]);
g_unix_set_fd_nonblocking (priv->cancel_pipe[0], TRUE, NULL);
g_unix_set_fd_nonblocking (priv->cancel_pipe[1], TRUE, NULL);
set_fd_close_exec (priv->cancel_pipe[0]);
set_fd_close_exec (priv->cancel_pipe[1]);

View File

@ -29,6 +29,10 @@
#include "gsocket.h"
#ifdef G_OS_UNIX
#include "glib-unix.h"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
@ -240,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;

View File

@ -135,6 +135,56 @@ g_unix_pipe_flags (int *fds,
return TRUE;
}
/**
* g_unix_set_fd_nonblocking:
* @fd: A file descriptor
* @nonblock: If %TRUE, set the descriptor to be non-blocking
* @error: a #GError
*
* Control the non-blocking state of the given file descriptor,
* according to @nonblock. On most systems this uses %O_NONBLOCK, but
* on some older ones may use %O_NDELAY.
*
* Returns: %TRUE if successful
*/
gboolean
g_unix_set_fd_nonblocking (gint fd,
gboolean nonblock,
GError **error)
{
#ifdef F_GETFL
glong fcntl_flags;
fcntl_flags = fcntl (fd, F_GETFL);
if (fcntl_flags == -1)
return g_unix_set_error_from_errno (error);
if (nonblock)
{
#ifdef O_NONBLOCK
fcntl_flags |= O_NONBLOCK;
#else
fcntl_flags |= O_NDELAY;
#endif
}
else
{
#ifdef O_NONBLOCK
fcntl_flags &= ~O_NONBLOCK;
#else
fcntl_flags &= ~O_NDELAY;
#endif
}
if (fcntl (fd, F_SETFL, fcntl_flags) == -1)
return g_unix_set_error_from_errno (error);
return TRUE;
#else
return g_unix_set_error_from_errno_saved (error, EINVAL);
#endif
}
/**
* g_unix_signal_source_new:
* @signum: A signal number

View File

@ -61,6 +61,10 @@ gboolean g_unix_pipe_flags (int *fds,
int flags,
GError **error);
gboolean g_unix_set_fd_nonblocking (gint fd,
gboolean nonblock,
GError **error);
GSource *g_unix_signal_source_new (int signum);
guint g_unix_signal_add_watch_full (int signum,

View File

@ -1983,6 +1983,7 @@ g_hostname_to_unicode
#ifdef G_OS_UNIX
g_unix_pipe_flags
g_unix_error_quark
g_unix_set_fd_nonblocking
g_unix_signal_source_new
g_unix_signal_add_watch_full
#endif

View File

@ -4638,7 +4638,7 @@ init_unix_signal_wakeup_state_unlocked (void)
if (!g_unix_pipe_flags (unix_signal_wake_up_pipe, FD_CLOEXEC, &error))
g_error ("Cannot create UNIX signal wake up pipe: %s\n", error->message);
fcntl (unix_signal_wake_up_pipe[1], F_SETFL, O_NONBLOCK | fcntl (unix_signal_wake_up_pipe[1], F_GETFL));
g_unix_set_fd_nonblocking (unix_signal_wake_up_pipe[1], TRUE, NULL);
/* We create a helper thread that polls on the wakeup pipe indefinitely */
if (g_thread_create (unix_signal_helper_thread, NULL, FALSE, &error) == NULL)