mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
glib-unix: Add O_NONBLOCK support to g_unix_open_pipe()
Add support for it, but don’t use it anywhere yet — this is an API addition, but currently doesn’t cause any functional changes. It’ll be used in the next commit. Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This commit is contained in:
parent
56c013cb6e
commit
5c65437d73
@ -249,7 +249,7 @@ watcher_init (void)
|
|||||||
gint pipe_fds[2];
|
gint pipe_fds[2];
|
||||||
|
|
||||||
/* fork a child to clean up when we are killed */
|
/* fork a child to clean up when we are killed */
|
||||||
if (!g_unix_open_pipe_internal (pipe_fds, TRUE))
|
if (!g_unix_open_pipe_internal (pipe_fds, TRUE, FALSE))
|
||||||
{
|
{
|
||||||
errsv = errno;
|
errsv = errno;
|
||||||
g_warning ("pipe() failed: %s", g_strerror (errsv));
|
g_warning ("pipe() failed: %s", g_strerror (errsv));
|
||||||
|
@ -398,8 +398,8 @@ stack_trace (const char * const *args)
|
|||||||
stack_trace_done = FALSE;
|
stack_trace_done = FALSE;
|
||||||
signal (SIGCHLD, stack_trace_sigchld);
|
signal (SIGCHLD, stack_trace_sigchld);
|
||||||
|
|
||||||
if (!g_unix_open_pipe_internal (in_fd, TRUE) ||
|
if (!g_unix_open_pipe_internal (in_fd, TRUE, FALSE) ||
|
||||||
!g_unix_open_pipe_internal (out_fd, TRUE))
|
!g_unix_open_pipe_internal (out_fd, TRUE, FALSE))
|
||||||
{
|
{
|
||||||
perror ("unable to open pipe");
|
perror ("unable to open pipe");
|
||||||
_exit (0);
|
_exit (0);
|
||||||
|
@ -74,11 +74,16 @@ g_unix_set_error_from_errno (GError **error,
|
|||||||
*
|
*
|
||||||
* Similar to the UNIX pipe() call, but on modern systems like Linux
|
* Similar to the UNIX pipe() call, but on modern systems like Linux
|
||||||
* uses the pipe2() system call, which atomically creates a pipe with
|
* uses the pipe2() system call, which atomically creates a pipe with
|
||||||
* the configured flags. The only supported flag currently is
|
* the configured flags.
|
||||||
* %FD_CLOEXEC. If for example you want to configure %O_NONBLOCK, that
|
|
||||||
* must still be done separately with fcntl().
|
|
||||||
*
|
*
|
||||||
* This function does not take %O_CLOEXEC, it takes %FD_CLOEXEC as if
|
* As of GLib 2.78, the supported flags are `FD_CLOEXEC` and `O_NONBLOCK`. Prior
|
||||||
|
* to GLib 2.78, only `FD_CLOEXEC` was supported — if you wanted to configure
|
||||||
|
* `O_NONBLOCK` then that had to be done separately with `fcntl()`.
|
||||||
|
*
|
||||||
|
* It is a programmer error to call this function with unsupported flags, and a
|
||||||
|
* critical warning will be raised.
|
||||||
|
*
|
||||||
|
* This function does not take `O_CLOEXEC`, it takes `FD_CLOEXEC` as if
|
||||||
* for fcntl(); these are different on Linux/glibc.
|
* for fcntl(); these are different on Linux/glibc.
|
||||||
*
|
*
|
||||||
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
|
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
|
||||||
@ -90,11 +95,12 @@ g_unix_open_pipe (int *fds,
|
|||||||
int flags,
|
int flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
/* We only support FD_CLOEXEC */
|
/* We only support FD_CLOEXEC and O_NONBLOCK */
|
||||||
g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
|
g_return_val_if_fail ((flags & (FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
|
||||||
|
|
||||||
if (!g_unix_open_pipe_internal (fds,
|
if (!g_unix_open_pipe_internal (fds,
|
||||||
(flags & FD_CLOEXEC) != 0))
|
(flags & FD_CLOEXEC) != 0,
|
||||||
|
(flags & O_NONBLOCK) != 0))
|
||||||
return g_unix_set_error_from_errno (error, errno);
|
return g_unix_set_error_from_errno (error, errno);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -41,15 +41,22 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
g_unix_open_pipe_internal (int *fds,
|
g_unix_open_pipe_internal (int *fds,
|
||||||
gboolean close_on_exec)
|
gboolean close_on_exec,
|
||||||
|
gboolean nonblock)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PIPE2
|
#ifdef HAVE_PIPE2
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int ecode;
|
int ecode;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (close_on_exec)
|
||||||
|
flags |= O_CLOEXEC;
|
||||||
|
if (nonblock)
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
|
||||||
/* Atomic */
|
/* Atomic */
|
||||||
ecode = pipe2 (fds, close_on_exec ? O_CLOEXEC : 0);
|
ecode = pipe2 (fds, flags);
|
||||||
if (ecode == -1 && errno != ENOSYS)
|
if (ecode == -1 && errno != ENOSYS)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else if (ecode == 0)
|
else if (ecode == 0)
|
||||||
@ -62,21 +69,44 @@ g_unix_open_pipe_internal (int *fds,
|
|||||||
if (pipe (fds) == -1)
|
if (pipe (fds) == -1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!close_on_exec)
|
if (close_on_exec)
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
|
|
||||||
fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1)
|
|
||||||
{
|
{
|
||||||
int saved_errno = errno;
|
if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
|
||||||
|
fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
close (fds[0]);
|
close (fds[0]);
|
||||||
close (fds[1]);
|
close (fds[1]);
|
||||||
fds[0] = -1;
|
fds[0] = -1;
|
||||||
fds[1] = -1;
|
fds[1] = -1;
|
||||||
|
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonblock)
|
||||||
|
{
|
||||||
|
#ifdef O_NONBLOCK
|
||||||
|
int flags = O_NONBLOCK;
|
||||||
|
#else
|
||||||
|
int flags = O_NDELAY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fcntl (fds[0], F_SETFL, flags) == -1 ||
|
||||||
|
fcntl (fds[1], F_SETFL, flags) == -1)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
close (fds[0]);
|
||||||
|
close (fds[1]);
|
||||||
|
fds[0] = -1;
|
||||||
|
fds[1] = -1;
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
Loading…
Reference in New Issue
Block a user