forked from enlightenment/efl
efl_net: better handling for SOCK_CLOEXEC.
On systems where SOCK_CLOEXEC is supported, give it to socket() and if accept4() is supported, then use it as well. Otherwise revert to fcntl().
This commit is contained in:
parent
164d9ddfde
commit
e3ee477140
|
@ -3036,3 +3036,32 @@ efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr)
|
|||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
efl_net_socket4(int domain, int type, int protocol, Eina_Bool close_on_exec)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (close_on_exec) type |= SOCK_CLOEXEC;
|
||||
#endif
|
||||
|
||||
fd = socket(domain, type, protocol);
|
||||
if (fd < 0) return fd;
|
||||
|
||||
#ifndef SOCK_CLOEXEC
|
||||
if (close_on_exec)
|
||||
{
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
|
||||
{
|
||||
int errno_bkp = errno;
|
||||
ERR("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
|
||||
close(fd);
|
||||
errno = errno_bkp;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -375,4 +375,6 @@ void ecore_con_mempool_shutdown(void);
|
|||
|
||||
Eina_Bool efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr);
|
||||
|
||||
int efl_net_socket4(int domain, int type, int protocol, Eina_Bool close_on_exec);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@ _efl_net_dialer_tcp_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Tcp_Data *pd EINA_
|
|||
{
|
||||
struct sockaddr_storage addr = {};
|
||||
char *str, *host, *port;
|
||||
int r, fd, extra_flags = 0;
|
||||
int r, fd;
|
||||
socklen_t addrlen;
|
||||
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")];
|
||||
|
||||
|
@ -118,14 +118,11 @@ _efl_net_dialer_tcp_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Tcp_Data *pd EINA_
|
|||
efl_event_callback_call(o, EFL_NET_DIALER_EVENT_RESOLVED, NULL);
|
||||
}
|
||||
|
||||
if (efl_net_socket_fd_close_on_exec_get(o))
|
||||
extra_flags |= SOCK_CLOEXEC;
|
||||
|
||||
fd = socket(addr.ss_family, SOCK_STREAM | extra_flags, IPPROTO_TCP);
|
||||
fd = efl_net_socket4(addr.ss_family, SOCK_STREAM, IPPROTO_TCP, efl_net_socket_fd_close_on_exec_get(o));
|
||||
if (fd < 0)
|
||||
{
|
||||
ERR("socket(%d, SOCK_STREAM | %#x, IPPROTO_TCP): %s",
|
||||
addr.ss_family, extra_flags, strerror(errno));
|
||||
ERR("socket(%d, SOCK_STREAM, IPPROTO_TCP): %s",
|
||||
addr.ss_family, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,32 @@ typedef struct _Efl_Net_Server_Fd_Data
|
|||
Eina_Bool reuse_port;
|
||||
} Efl_Net_Server_Fd_Data;
|
||||
|
||||
static int
|
||||
efl_net_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, Eina_Bool close_on_exec)
|
||||
{
|
||||
#ifdef HAVE_ACCEPT4
|
||||
int flags = 0;
|
||||
if (close_on_exec) flags |= SOCK_CLOEXEC;
|
||||
return accept4(fd, addr, addrlen, flags);
|
||||
#else
|
||||
int client = accept(fd, addr, addrlen);
|
||||
if (client < 0) return client;
|
||||
|
||||
if (close_on_exec)
|
||||
{
|
||||
if (fcntl(client, F_SETFD, FD_CLOEXEC) < 0)
|
||||
{
|
||||
int errno_bkp = errno;
|
||||
ERR("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", client, strerror(errno));
|
||||
close(client);
|
||||
errno = errno_bkp;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return client;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_net_server_fd_event_read(void *data EINA_UNUSED, const Eo_Event *event)
|
||||
{
|
||||
|
@ -39,7 +65,7 @@ _efl_net_server_fd_event_read(void *data EINA_UNUSED, const Eo_Event *event)
|
|||
unsigned int count, limit;
|
||||
Eina_Bool reject_excess, do_reject = EINA_FALSE;
|
||||
struct sockaddr_storage addr;
|
||||
int client, fd, flags = 0;
|
||||
int client, fd;
|
||||
socklen_t addrlen;
|
||||
|
||||
count = efl_net_server_clients_count_get(o);
|
||||
|
@ -57,15 +83,9 @@ _efl_net_server_fd_event_read(void *data EINA_UNUSED, const Eo_Event *event)
|
|||
|
||||
fd = efl_loop_fd_get(o);
|
||||
|
||||
if (efl_net_server_fd_close_on_exec_get(o))
|
||||
flags |= SOCK_CLOEXEC;
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
#ifdef HAVE_ACCEPT4
|
||||
client = accept4(fd, (struct sockaddr *)&addr, &addrlen, flags);
|
||||
#else
|
||||
client = accept(fd, (struct sockaddr *)&addr, &addrlen);
|
||||
#endif
|
||||
client = efl_net_accept4(fd, (struct sockaddr *)&addr, &addrlen,
|
||||
efl_net_server_fd_close_on_exec_get(o));
|
||||
if (client < 0)
|
||||
{
|
||||
Eina_Error err = errno;
|
||||
|
@ -74,11 +94,6 @@ _efl_net_server_fd_event_read(void *data EINA_UNUSED, const Eo_Event *event)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ACCEPT4
|
||||
if (fcntl(fd, F_SETFD, flags) < 0)
|
||||
ERR("fcntl(%d, F_SETFD, %#x): %s", fd, flags, strerror(errno));
|
||||
#endif
|
||||
|
||||
if (do_reject)
|
||||
efl_net_server_fd_client_reject(o, client);
|
||||
else
|
||||
|
|
|
@ -34,7 +34,7 @@ _efl_net_server_tcp_efl_net_server_serve(Eo *o, void *pd EINA_UNUSED, const char
|
|||
{
|
||||
struct sockaddr_storage addr = {};
|
||||
char *str, *host, *port;
|
||||
int r, fd, extra_flags = 0;
|
||||
int r, fd;
|
||||
socklen_t addrlen;
|
||||
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")];
|
||||
Eina_Error err = 0;
|
||||
|
@ -97,15 +97,13 @@ _efl_net_server_tcp_efl_net_server_serve(Eo *o, void *pd EINA_UNUSED, const char
|
|||
if (efl_net_ip_port_fmt(buf, sizeof(buf), (struct sockaddr *)&addr))
|
||||
efl_net_server_address_set(o, buf);
|
||||
|
||||
if (efl_net_server_fd_close_on_exec_get(o))
|
||||
extra_flags |= SOCK_CLOEXEC;
|
||||
|
||||
fd = socket(addr.ss_family, SOCK_STREAM | extra_flags, IPPROTO_TCP);
|
||||
fd = efl_net_socket4(addr.ss_family, SOCK_STREAM, IPPROTO_TCP,
|
||||
efl_net_server_fd_close_on_exec_get(o));
|
||||
if (fd < 0)
|
||||
{
|
||||
err = errno;
|
||||
ERR("socket(%d, SOCK_STREAM | %#x, IPPROTO_TCP): %s",
|
||||
addr.ss_family, extra_flags, strerror(errno));
|
||||
ERR("socket(%d, SOCK_STREAM, IPPROTO_TCP): %s",
|
||||
addr.ss_family, strerror(errno));
|
||||
goto error_socket;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue