fd_util: added O_NONBLOCK functions
Changed the wrappers for pipe(), socket(), accept(). On WIN32, this does not work for pipe().
This commit is contained in:
parent
b043ade456
commit
f66edccffd
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "event_pipe.h"
|
#include "event_pipe.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "fd_util.h"
|
#include "fd_util.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -85,13 +84,9 @@ void event_pipe_init(void)
|
|||||||
GIOChannel *channel;
|
GIOChannel *channel;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = pipe_cloexec(event_pipe);
|
ret = pipe_cloexec_nonblock(event_pipe);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
g_error("Couldn't open pipe: %s", strerror(errno));
|
g_error("Couldn't open pipe: %s", strerror(errno));
|
||||||
#ifndef WIN32
|
|
||||||
if (set_nonblocking(event_pipe[1]) < 0)
|
|
||||||
g_error("Couldn't set non-blocking I/O: %s", strerror(errno));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
channel = g_io_channel_unix_new(event_pipe[0]);
|
channel = g_io_channel_unix_new(event_pipe[0]);
|
||||||
event_pipe_source_id = g_io_add_watch(channel, G_IO_IN,
|
event_pipe_source_id = g_io_add_watch(channel, G_IO_IN,
|
||||||
|
@ -68,6 +68,29 @@ fd_set_cloexec(int fd, bool enable)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables non-blocking mode for the specified file descriptor. On
|
||||||
|
* WIN32, this function only works for sockets.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
fd_set_nonblock(int fd)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
u_long val = 1;
|
||||||
|
return ioctlsocket(fd, FIONBIO, &val);
|
||||||
|
#else
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
assert(fd >= 0);
|
||||||
|
|
||||||
|
flags = fcntl(fd, F_GETFL);
|
||||||
|
if (flags < 0)
|
||||||
|
return flags;
|
||||||
|
|
||||||
|
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_cloexec(const char *path_fs, int flags)
|
open_cloexec(const char *path_fs, int flags)
|
||||||
{
|
{
|
||||||
@ -108,7 +131,7 @@ creat_cloexec(const char *path_fs, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pipe_cloexec(int fd[2])
|
pipe_cloexec_nonblock(int fd[2])
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
return _pipe(event_pipe, 512, _O_BINARY);
|
return _pipe(event_pipe, 512, _O_BINARY);
|
||||||
@ -116,7 +139,7 @@ pipe_cloexec(int fd[2])
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef HAVE_PIPE2
|
#ifdef HAVE_PIPE2
|
||||||
ret = pipe2(fd, O_CLOEXEC);
|
ret = pipe2(fd, O_CLOEXEC|O_NONBLOCK);
|
||||||
if (ret >= 0 || errno != ENOSYS)
|
if (ret >= 0 || errno != ENOSYS)
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
@ -125,6 +148,11 @@ pipe_cloexec(int fd[2])
|
|||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
fd_set_cloexec(fd[0], true);
|
fd_set_cloexec(fd[0], true);
|
||||||
fd_set_cloexec(fd[1], true);
|
fd_set_cloexec(fd[1], true);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
fd_set_nonblock(fd[0]);
|
||||||
|
fd_set_nonblock(fd[1]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -132,12 +160,12 @@ pipe_cloexec(int fd[2])
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
socket_cloexec(int domain, int type, int protocol)
|
socket_cloexec_nonblock(int domain, int type, int protocol)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
#ifdef SOCK_CLOEXEC
|
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
|
||||||
fd = socket(domain, type | SOCK_CLOEXEC, protocol);
|
fd = socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
|
||||||
if (fd >= 0 || errno != EINVAL)
|
if (fd >= 0 || errno != EINVAL)
|
||||||
return fd;
|
return fd;
|
||||||
#endif
|
#endif
|
||||||
@ -150,13 +178,15 @@ socket_cloexec(int domain, int type, int protocol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r)
|
accept_cloexec_nonblock(int fd, struct sockaddr *address,
|
||||||
|
size_t *address_length_r)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
socklen_t address_length = *address_length_r;
|
socklen_t address_length = *address_length_r;
|
||||||
|
|
||||||
#ifdef HAVE_ACCEPT4
|
#ifdef HAVE_ACCEPT4
|
||||||
ret = accept4(fd, address, &address_length, SOCK_CLOEXEC);
|
ret = accept4(fd, address, &address_length,
|
||||||
|
SOCK_CLOEXEC|SOCK_NONBLOCK);
|
||||||
if (ret >= 0 || errno != ENOSYS) {
|
if (ret >= 0 || errno != ENOSYS) {
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
*address_length_r = address_length;
|
*address_length_r = address_length;
|
||||||
@ -168,6 +198,7 @@ accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r)
|
|||||||
ret = accept(fd, address, &address_length);
|
ret = accept(fd, address, &address_length);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
fd_set_cloexec(ret, true);
|
fd_set_cloexec(ret, true);
|
||||||
|
fd_set_nonblock(ret);
|
||||||
*address_length_r = address_length;
|
*address_length_r = address_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,23 +49,27 @@ creat_cloexec(const char *path_fs, int mode);
|
|||||||
/**
|
/**
|
||||||
* Wrapper for pipe(), which sets the CLOEXEC flag (atomically if
|
* Wrapper for pipe(), which sets the CLOEXEC flag (atomically if
|
||||||
* supported by the OS).
|
* supported by the OS).
|
||||||
|
*
|
||||||
|
* On systems that supports it (everybody except for Windows), it also
|
||||||
|
* sets the NONBLOCK flag.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
pipe_cloexec(int fd[2]);
|
pipe_cloexec_nonblock(int fd[2]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for socket(), which sets the CLOEXEC flag (atomically if
|
* Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag
|
||||||
* supported by the OS).
|
* (atomically if supported by the OS).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
socket_cloexec(int domain, int type, int protocol);
|
socket_cloexec_nonblock(int domain, int type, int protocol);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for accept(), which sets the CLOEXEC flag (atomically if
|
* Wrapper for accept(), which sets the CLOEXEC and the NONBLOCK flags
|
||||||
* supported by the OS).
|
* (atomically if supported by the OS).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
accept_cloexec(int fd, struct sockaddr *address, size_t *address_length_r);
|
accept_cloexec_nonblock(int fd, struct sockaddr *address,
|
||||||
|
size_t *address_length_r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for inotify_init(), which sets the CLOEXEC flag (atomically
|
* Wrapper for inotify_init(), which sets the CLOEXEC flag (atomically
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "socket_util.h"
|
#include "socket_util.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "fd_util.h"
|
#include "fd_util.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
@ -429,10 +428,9 @@ listen_in_event(G_GNUC_UNUSED GIOChannel *source,
|
|||||||
struct sockaddr_storage sa;
|
struct sockaddr_storage sa;
|
||||||
size_t sa_length = sizeof(sa);
|
size_t sa_length = sizeof(sa);
|
||||||
|
|
||||||
fd = accept_cloexec(listen_fd, (struct sockaddr*)&sa, &sa_length);
|
fd = accept_cloexec_nonblock(listen_fd, (struct sockaddr*)&sa,
|
||||||
|
&sa_length);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
set_nonblocking(fd);
|
|
||||||
|
|
||||||
client_new(fd, (struct sockaddr*)&sa, sa_length,
|
client_new(fd, (struct sockaddr*)&sa, sa_length,
|
||||||
get_remote_uid(fd));
|
get_remote_uid(fd));
|
||||||
} else if (fd < 0 && errno != EINTR) {
|
} else if (fd < 0 && errno != EINTR) {
|
||||||
|
@ -195,7 +195,8 @@ httpd_listen_in_event(G_GNUC_UNUSED GIOChannel *source,
|
|||||||
/* the listener socket has become readable - a client has
|
/* the listener socket has become readable - a client has
|
||||||
connected */
|
connected */
|
||||||
|
|
||||||
fd = accept_cloexec(httpd->fd, (struct sockaddr*)&sa, &sa_length);
|
fd = accept_cloexec_nonblock(httpd->fd, (struct sockaddr*)&sa,
|
||||||
|
&sa_length);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
/* can we allow additional client */
|
/* can we allow additional client */
|
||||||
if (httpd->open &&
|
if (httpd->open &&
|
||||||
|
@ -103,7 +103,7 @@ socket_bind_listen(int domain, int type, int protocol,
|
|||||||
int passcred = 1;
|
int passcred = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fd = socket_cloexec(domain, type, protocol);
|
fd = socket_cloexec_nonblock(domain, type, protocol);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
g_set_error(error, listen_quark(), errno,
|
g_set_error(error, listen_quark(), errno,
|
||||||
"Failed to create socket: %s", g_strerror(errno));
|
"Failed to create socket: %s", g_strerror(errno));
|
||||||
|
Loading…
Reference in New Issue
Block a user