barbieri pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=e3ee477140bb760dfffc8e32c0a3e9a961664c3d

commit e3ee477140bb760dfffc8e32c0a3e9a961664c3d
Author: Gustavo Sverzut Barbieri <[email protected]>
Date:   Wed Aug 24 12:34:59 2016 -0300

    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().
---
 src/lib/ecore_con/ecore_con.c          | 29 +++++++++++++++++++++++
 src/lib/ecore_con/ecore_con_private.h  |  2 ++
 src/lib/ecore_con/efl_net_dialer_tcp.c | 11 ++++-----
 src/lib/ecore_con/efl_net_server_fd.c  | 43 +++++++++++++++++++++++-----------
 src/lib/ecore_con/efl_net_server_tcp.c | 12 ++++------
 5 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
index e040a71..8340c3d 100644
--- a/src/lib/ecore_con/ecore_con.c
+++ b/src/lib/ecore_con/ecore_con.c
@@ -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;
+}
diff --git a/src/lib/ecore_con/ecore_con_private.h 
b/src/lib/ecore_con/ecore_con_private.h
index 089f864..e2fab7a 100644
--- a/src/lib/ecore_con/ecore_con_private.h
+++ b/src/lib/ecore_con/ecore_con_private.h
@@ -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
diff --git a/src/lib/ecore_con/efl_net_dialer_tcp.c 
b/src/lib/ecore_con/efl_net_dialer_tcp.c
index b835d93..88f78fe 100644
--- a/src/lib/ecore_con/efl_net_dialer_tcp.c
+++ b/src/lib/ecore_con/efl_net_dialer_tcp.c
@@ -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;
      }
 
diff --git a/src/lib/ecore_con/efl_net_server_fd.c 
b/src/lib/ecore_con/efl_net_server_fd.c
index 06af641..0365669 100644
--- a/src/lib/ecore_con/efl_net_server_fd.c
+++ b/src/lib/ecore_con/efl_net_server_fd.c
@@ -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
diff --git a/src/lib/ecore_con/efl_net_server_tcp.c 
b/src/lib/ecore_con/efl_net_server_tcp.c
index 25bfb01..b904cbb 100644
--- a/src/lib/ecore_con/efl_net_server_tcp.c
+++ b/src/lib/ecore_con/efl_net_server_tcp.c
@@ -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;
      }
 

-- 


Reply via email to