efl_io_closer: add close_on_exec and close_on_destructor properties.
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Mon, 12 Sep 2016 15:23:29 +0000 (12:23 -0300)
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Mon, 12 Sep 2016 16:18:28 +0000 (13:18 -0300)
the purpose of these properties are to make it more uniform the
handling of these auto-close behavior.

21 files changed:
src/examples/ecore/efl_net_server_example.c
src/lib/ecore/efl_io_closer_fd.c
src/lib/ecore/efl_io_closer_fd.eo
src/lib/ecore/efl_io_copier.c
src/lib/ecore/efl_io_copier.eo
src/lib/ecore/efl_io_file.c
src/lib/ecore/efl_io_file.eo
src/lib/ecore_con/efl_net_dialer_http.c
src/lib/ecore_con/efl_net_dialer_http.eo
src/lib/ecore_con/efl_net_dialer_tcp.c
src/lib/ecore_con/efl_net_dialer_websocket.c
src/lib/ecore_con/efl_net_dialer_websocket.eo
src/lib/ecore_con/efl_net_server_fd.eo
src/lib/ecore_con/efl_net_server_tcp.c
src/lib/ecore_con/efl_net_socket_fd.c
src/lib/ecore_con/efl_net_socket_fd.eo
src/lib/efl/interfaces/efl_io_buffer.c
src/lib/efl/interfaces/efl_io_buffer.eo
src/lib/efl/interfaces/efl_io_closer.eo
src/lib/efl/interfaces/efl_io_queue.c
src/lib/efl/interfaces/efl_io_queue.eo

index 620a94e..2ffcdee 100644 (file)
@@ -58,8 +58,7 @@ _echo_copier_done(void *data EINA_UNUSED, const Efl_Event *event)
 {
    Eo *copier = event->object;
    fprintf(stderr, "INFO: echo copier done, close and del %p\n", copier);
-   efl_io_closer_close(copier);
-   efl_del(copier);
+   efl_del(copier); /* set to close_on_destructor, will auto close copier and client */
 }
 
 static void
@@ -73,7 +72,6 @@ _echo_copier_error(void *data EINA_UNUSED, const Efl_Event *event)
    fprintf(stderr, "ERROR: echo copier %p failed %d, close and del.\n",
            copier, *perr);
 
-   efl_io_closer_close(copier);
    efl_del(copier);
 }
 
@@ -123,7 +121,7 @@ _send_recv_done(Send_Recv_Data *d, Eo *copier)
 
    efl_del(copier);
    if (d->send_copier || d->recv_copier) return;
-   efl_io_closer_close(d->client);
+   efl_io_closer_close(d->client); /* manually close once both copiers are done */
    _send_recv_free(d);
 }
 
@@ -305,7 +303,8 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
         Eo *echo_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client),
                                   efl_io_copier_source_set(efl_added, client),
                                   efl_io_copier_destination_set(efl_added, client),
-                                  efl_event_callback_array_add(efl_added, echo_copier_cbs(), client)
+                                  efl_event_callback_array_add(efl_added, echo_copier_cbs(), client),
+                                  efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE) /* we want to auto-close as we have a single copier */
                                   );
 
         fprintf(stderr, "INFO: using an echo copier=%p for client %s\n",
@@ -346,7 +345,8 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
         d->send_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client),
                                  efl_io_copier_source_set(efl_added, send_buffer),
                                  efl_io_copier_destination_set(efl_added, client),
-                                 efl_event_callback_array_add(efl_added, send_copier_cbs(), d)
+                                 efl_event_callback_array_add(efl_added, send_copier_cbs(), d),
+                                 efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE) /* we must wait both copiers to finish before we close! */
                                  );
 
         fprintf(stderr, "INFO: using sender buffer %p with copier %p for client %s\n",
@@ -361,7 +361,8 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
         d->recv_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client),
                                  efl_io_copier_source_set(efl_added, client),
                                  efl_io_copier_destination_set(efl_added, recv_buffer),
-                                 efl_event_callback_array_add(efl_added, recv_copier_cbs(), d)
+                                 efl_event_callback_array_add(efl_added, recv_copier_cbs(), d),
+                                 efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE) /* we must wait both copiers to finish before we close! */
                                  );
 
         fprintf(stderr, "INFO: using receiver buffer %p with copier %p for client %s\n",
index a0ad5ec..db2bcaa 100644 (file)
@@ -5,6 +5,7 @@
 #endif
 
 #include <Ecore.h>
+#include <fcntl.h>
 #include "ecore_private.h"
 
 #define MY_CLASS EFL_IO_CLOSER_FD_CLASS
@@ -12,6 +13,8 @@
 typedef struct _Efl_Io_Closer_Fd_Data
 {
    int fd;
+   Eina_Bool close_on_exec;
+   Eina_Bool close_on_destructor;
 } Efl_Io_Closer_Fd_Data;
 
 EOLIAN static void
@@ -46,4 +49,83 @@ _efl_io_closer_fd_efl_io_closer_closed_get(Eo *o, Efl_Io_Closer_Fd_Data *pd EINA
    return efl_io_closer_fd_closer_fd_get(o) < 0;
 }
 
+EOLIAN static Eina_Bool
+_efl_io_closer_fd_efl_io_closer_close_on_exec_set(Eo *o, Efl_Io_Closer_Fd_Data *pd, Eina_Bool close_on_exec)
+{
+#ifdef _WIN32
+   DBG("close on exec is not supported on windows");
+   pd->close_on_exec = close_on_exec;
+   return EINA_FALSE;
+#else
+   int flags, fd;
+   Eina_Bool old = pd->close_on_exec;
+
+   pd->close_on_exec = close_on_exec;
+
+   fd = efl_io_closer_fd_closer_fd_get(o);
+   if (fd < 0) return EINA_TRUE; /* postpone until fd_set(), users
+                                  * must apply MANUALLY if it's not
+                                  * already set!
+                                  */
+
+   flags = fcntl(fd, F_GETFD);
+   if (flags < 0)
+     {
+        ERR("fcntl(%d, F_GETFD): %s", fd, strerror(errno));
+        pd->close_on_exec = old;
+        return EINA_FALSE;
+     }
+   if (close_on_exec)
+     flags |= FD_CLOEXEC;
+   else
+     flags &= (~FD_CLOEXEC);
+   if (fcntl(fd, F_SETFD, flags) < 0)
+     {
+        ERR("fcntl(%d, F_SETFD, %#x): %s", fd, flags, strerror(errno));
+        pd->close_on_exec = old;
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+#endif
+}
+
+EOLIAN static Eina_Bool
+_efl_io_closer_fd_efl_io_closer_close_on_exec_get(Eo *o, Efl_Io_Closer_Fd_Data *pd)
+{
+#ifdef _WIN32
+   return pd->close_on_exec;
+#else
+   int flags, fd;
+
+   fd = efl_io_closer_fd_closer_fd_get(o);
+   if (fd < 0) return pd->close_on_exec;
+
+   /* if there is a fd, always query it directly as it may be modified
+    * elsewhere by nasty users.
+    */
+   flags = fcntl(fd, F_GETFD);
+   if (flags < 0)
+     {
+        ERR("fcntl(%d, F_GETFD): %s", fd, strerror(errno));
+        return EINA_FALSE;
+     }
+
+   pd->close_on_exec = !!(flags & FD_CLOEXEC); /* sync */
+   return pd->close_on_exec;
+#endif
+}
+
+EOLIAN static void
+_efl_io_closer_fd_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Io_Closer_Fd_Data *pd, Eina_Bool close_on_destructor)
+{
+   pd->close_on_destructor = close_on_destructor;
+}
+
+EOLIAN static Eina_Bool
+_efl_io_closer_fd_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Io_Closer_Fd_Data *pd)
+{
+   return pd->close_on_destructor;
+}
+
 #include "efl_io_closer_fd.eo.c"
index 35f881b..853f2b4 100644 (file)
@@ -17,5 +17,7 @@ mixin Efl.Io.Closer.Fd (Efl.Io.Closer) {
     implements {
         Efl.Io.Closer.close;
         Efl.Io.Closer.closed.get;
+        Efl.Io.Closer.close_on_exec;
+        Efl.Io.Closer.close_on_destructor;
     }
 }
index 457007d..23e77ac 100644 (file)
@@ -23,6 +23,8 @@ typedef struct _Efl_Io_Copier_Data
    } progress;
    Eina_Bool closed;
    Eina_Bool done;
+   Eina_Bool close_on_exec;
+   Eina_Bool close_on_destructor;
 } Efl_Io_Copier_Data;
 
 static void _efl_io_copier_write(Eo *o, Efl_Io_Copier_Data *pd);
@@ -394,6 +396,8 @@ _efl_io_copier_source_set(Eo *o, Efl_Io_Copier_Data *pd, Efl_Io_Reader *source)
 
         if (efl_isa(pd->source, EFL_IO_CLOSER_MIXIN))
           {
+             efl_io_closer_close_on_exec_set(pd->source, efl_io_closer_close_on_exec_get(o));
+             efl_io_closer_close_on_destructor_set(pd->source, efl_io_closer_close_on_destructor_get(o));
              efl_event_callback_add(pd->source, EFL_IO_CLOSER_EVENT_CLOSED,
                                      _efl_io_copier_source_closed, o);
           }
@@ -471,6 +475,8 @@ _efl_io_copier_destination_set(Eo *o, Efl_Io_Copier_Data *pd, Efl_Io_Writer *des
 
         if (efl_isa(pd->destination, EFL_IO_CLOSER_MIXIN))
           {
+             efl_io_closer_close_on_exec_set(pd->destination, efl_io_closer_close_on_exec_get(o));
+             efl_io_closer_close_on_destructor_set(pd->destination, efl_io_closer_close_on_destructor_get(o));
              efl_event_callback_add(pd->destination, EFL_IO_CLOSER_EVENT_CLOSED,
                                      _efl_io_copier_destination_closed, o);
           }
@@ -648,6 +654,8 @@ EOLIAN static Eo *
 _efl_io_copier_efl_object_constructor(Eo *o, Efl_Io_Copier_Data *pd)
 {
    pd->buf = eina_binbuf_new();
+   pd->close_on_exec = EINA_TRUE;
+   pd->close_on_destructor = EINA_TRUE;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(pd->buf, NULL);
 
@@ -680,6 +688,10 @@ _efl_io_copier_efl_object_destructor(Eo *o, Efl_Io_Copier_Data *pd)
 {
    _COPIER_DBG(o, pd);
 
+   if (efl_io_closer_close_on_destructor_get(o) &&
+       (!efl_io_closer_closed_get(o)))
+     efl_io_closer_close(o);
+
    efl_io_copier_source_set(o, NULL);
    efl_io_copier_destination_set(o, NULL);
 
@@ -712,4 +724,44 @@ _efl_io_copier_efl_object_destructor(Eo *o, Efl_Io_Copier_Data *pd)
      }
 }
 
+EOLIAN static Eina_Bool
+_efl_io_copier_efl_io_closer_close_on_exec_set(Eo *o EINA_UNUSED, Efl_Io_Copier_Data *pd, Eina_Bool close_on_exec)
+{
+   if (pd->close_on_exec == close_on_exec) return EINA_TRUE;
+   pd->close_on_exec = close_on_exec;
+
+   if (pd->source && efl_isa(pd->source, EFL_IO_CLOSER_MIXIN))
+     efl_io_closer_close_on_exec_set(pd->source, close_on_exec);
+
+   if (pd->destination && efl_isa(pd->destination, EFL_IO_CLOSER_MIXIN))
+     efl_io_closer_close_on_exec_set(pd->destination, close_on_exec);
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_efl_io_copier_efl_io_closer_close_on_exec_get(Eo *o EINA_UNUSED, Efl_Io_Copier_Data *pd)
+{
+   return pd->close_on_exec;
+}
+
+EOLIAN static void
+_efl_io_copier_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Io_Copier_Data *pd, Eina_Bool close_on_destructor)
+{
+   if (pd->close_on_destructor == close_on_destructor) return;
+   pd->close_on_destructor = close_on_destructor;
+
+   if (pd->source && efl_isa(pd->source, EFL_IO_CLOSER_MIXIN))
+     efl_io_closer_close_on_destructor_set(pd->source, close_on_destructor);
+
+   if (pd->destination && efl_isa(pd->destination, EFL_IO_CLOSER_MIXIN))
+     efl_io_closer_close_on_destructor_set(pd->destination, close_on_destructor);
+}
+
+EOLIAN static Eina_Bool
+_efl_io_copier_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Io_Copier_Data *pd)
+{
+   return pd->close_on_destructor;
+}
+
 #include "efl_io_copier.eo.c"
index 4a14a07..28dcf82 100644 (file)
@@ -15,6 +15,10 @@ class Efl.Io.Copier (Efl.Loop_User, Efl.Io.Closer) {
       If @Efl.Io.Closer.close is called, then it will be called on
       @.source and @.destination if they implement those interfaces.
 
+      @Efl.Io.Closer.close_on_exec and
+      @Efl.Io.Closer.close_on_destructor are respected and applied to
+      both source and destination. Both default to $true.
+
       @since 1.19
     ]]
 
@@ -108,5 +112,7 @@ class Efl.Io.Copier (Efl.Loop_User, Efl.Io.Closer) {
        Efl.Object.finalize;
        Efl.Io.Closer.close;
        Efl.Io.Closer.closed.get;
+       Efl.Io.Closer.close_on_exec;
+       Efl.Io.Closer.close_on_destructor;
     }
 }
index 40c0346..a5ec38f 100644 (file)
@@ -65,8 +65,15 @@ _efl_io_file_efl_loop_fd_fd_file_set(Eo *o, Efl_Io_File_Data *pd, int fd)
 EOLIAN static void
 _efl_io_file_flags_set(Eo *o, Efl_Io_File_Data *pd, uint32_t flags)
 {
+   Eina_Bool close_on_exec;
+
    EINA_SAFETY_ON_TRUE_RETURN(efl_finalized_get(o));
+
    pd->flags = flags;
+
+   close_on_exec = !!(flags & O_CLOEXEC);
+   if (close_on_exec != efl_io_closer_close_on_exec_get(o))
+     efl_io_closer_close_on_exec_set(o, close_on_exec);
 }
 
 EOLIAN static uint32_t
@@ -88,10 +95,24 @@ _efl_io_file_mode_get(Eo *o EINA_UNUSED, Efl_Io_File_Data *pd)
    return pd->mode;
 }
 
+EOLIAN static Eo *
+_efl_io_file_efl_object_constructor(Eo *o, Efl_Io_File_Data *pd)
+{
+   pd->flags = O_RDONLY | O_CLOEXEC;
+
+   o = efl_constructor(efl_super(o, MY_CLASS));
+
+   efl_io_closer_close_on_exec_set(o, EINA_TRUE);
+   efl_io_closer_close_on_destructor_set(o, EINA_TRUE);
+
+   return o;
+}
+
 EOLIAN static void
 _efl_io_file_efl_object_destructor(Eo *o, Efl_Io_File_Data *pd)
 {
-   if (!efl_io_closer_closed_get(o))
+   if (efl_io_closer_close_on_destructor_get(o) &&
+       (!efl_io_closer_closed_get(o)))
      efl_io_closer_close(o);
 
    efl_destructor(efl_super(o, MY_CLASS));
@@ -192,4 +213,15 @@ _efl_io_file_efl_io_positioner_seek(Eo *o, Efl_Io_File_Data *pd, int64_t offset,
    return 0;
 }
 
+EOLIAN static Eina_Bool
+_efl_io_file_efl_io_closer_close_on_exec_set(Eo *o, Efl_Io_File_Data *pd, Eina_Bool close_on_exec)
+{
+   if (close_on_exec)
+     pd->flags |= O_CLOEXEC;
+   else
+     pd->flags &= (~O_CLOEXEC);
+
+   return efl_io_closer_close_on_exec_set(efl_super(o, MY_CLASS), close_on_exec);
+}
+
 #include "efl_io_file.eo.c"
index 6139634..841f173 100644 (file)
@@ -1,14 +1,24 @@
 class Efl.Io.File (Efl.Loop.Fd, Efl.File, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Efl.Io.Closer.Fd, Efl.Io.Sizer.Fd, Efl.Io.Positioner.Fd) {
     [[File access (open, close, read, write, lseek, ftruncate)
 
-      Files are closed automatically (@Efl.Io.Closer.Fd) on destruction.
+      @Efl.Io.Closer.close_on_exec and
+      @Efl.Io.Closer.close_on_destructor are respected and default to
+      $true. @Efl.Io.Closer.close_on_exec.set sets flag O_CLOEXEC.
 
       @since 1.19
     ]]
 
     methods {
         @property flags {
-            [[bitwise OR'ed flags to open the file, like O_CREAT, O_CLOEXEC...]]
+            [[bitwise OR'ed flags to open the file, like O_CREAT, O_APPEND...
+
+              Defaults to O_RDONLY | O_CLOEXEC.
+
+              The flag O_CLOEXEC will be also managed by
+              @Efl.Io.Closer.close_on_exec.set. Setting the property
+              after the file is opened will change its blocking
+              behavior.
+            ]]
             get {
             }
 
@@ -36,6 +46,7 @@ class Efl.Io.File (Efl.Loop.Fd, Efl.File, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Ef
     }
 
     implements {
+        Efl.Object.constructor;
         Efl.Object.destructor;
         Efl.Object.finalize;
         Efl.Loop.Fd.fd_file.set;
@@ -43,6 +54,7 @@ class Efl.Io.File (Efl.Loop.Fd, Efl.File, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Ef
         Efl.Io.Reader.read;
         Efl.Io.Writer.write;
         Efl.Io.Closer.close;
+        Efl.Io.Closer.close_on_exec.set;
         Efl.Io.Sizer.resize;
         Efl.Io.Positioner.seek;
     }
index 31832f5..e1de230 100644 (file)
@@ -24,6 +24,7 @@
 #include "ecore_con_url_curl.h"
 
 #include <ctype.h>
+#include <fcntl.h>
 
 /* improve usage of lazy-loaded library in _c-> */
 #define curl_easy_strerror(...) _c->curl_easy_strerror(__VA_ARGS__)
@@ -210,6 +211,8 @@ typedef struct
    uint8_t pause;
    Eina_Bool connected;
    Eina_Bool closed;
+   Eina_Bool close_on_exec;
+   Eina_Bool close_on_destructor;
    Eina_Bool eos;
    Eina_Bool can_read;
    Eina_Bool can_write;
@@ -1096,7 +1099,7 @@ _efl_net_dialer_http_socket_open(void *data, curlsocktype purpose EINA_UNUSED, s
    Eo *o = data;
    Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS);
 
-   pd->fd = socket(addr->family, addr->socktype, addr->protocol);
+   pd->fd = efl_net_socket4(addr->family, addr->socktype, addr->protocol, pd->close_on_exec);
    if (pd->fd < 0)
      ERR("could not create curl socket family=%d, type=%d, protocol=%d",
          addr->family, addr->socktype, addr->protocol);
@@ -1192,7 +1195,8 @@ _efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd)
         pd->pending_close = NULL;
         efl_io_closer_close(o);
      }
-   else if (!efl_io_closer_closed_get(o))
+   else if (efl_io_closer_close_on_destructor_get(o) &&
+            (!efl_io_closer_closed_get(o)))
      efl_io_closer_close(o);
 
    efl_net_dialer_http_response_headers_clear(o);
@@ -1597,6 +1601,61 @@ _efl_net_dialer_http_efl_io_closer_closed_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_
    return pd->closed || (!!pd->pending_close);
 }
 
+EOLIAN static Eina_Bool
+_efl_net_dialer_http_efl_io_closer_close_on_exec_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, Eina_Bool close_on_exec)
+{
+#ifdef _WIN32
+   DBG("close on exec is not supported on windows");
+   pd->close_on_exec = close_on_exec;
+   return EINA_FALSE;
+#else
+   int flags;
+   Eina_Bool old = pd->close_on_exec;
+
+   pd->close_on_exec = close_on_exec;
+
+   if (pd->fd < 0) return EINA_TRUE; /* postpone until _efl_net_dialer_http_socket_open */
+
+   flags = fcntl(pd->fd, F_GETFD);
+   if (flags < 0)
+     {
+        ERR("fcntl(%d, F_GETFD): %s", pd->fd, strerror(errno));
+        pd->close_on_exec = old;
+        return EINA_FALSE;
+     }
+   if (close_on_exec)
+     flags |= FD_CLOEXEC;
+   else
+     flags &= (~FD_CLOEXEC);
+   if (fcntl(pd->fd, F_SETFD, flags) < 0)
+     {
+        ERR("fcntl(%d, F_SETFD, %#x): %s", pd->fd, flags, strerror(errno));
+        pd->close_on_exec = old;
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+#endif
+}
+
+EOLIAN static Eina_Bool
+_efl_net_dialer_http_efl_io_closer_close_on_exec_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd)
+{
+   return pd->close_on_exec;
+}
+
+EOLIAN static void
+_efl_net_dialer_http_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, Eina_Bool close_on_destructor)
+{
+   pd->close_on_destructor = close_on_destructor;
+}
+
+EOLIAN static Eina_Bool
+_efl_net_dialer_http_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd)
+{
+   return pd->close_on_destructor;
+}
+
 EOLIAN static Eina_Error
 _efl_net_dialer_http_efl_io_sizer_resize(Eo *o, Efl_Net_Dialer_Http_Data *pd, uint64_t size)
 {
index f1b42dd..f7c439a 100644 (file)
@@ -342,6 +342,8 @@ class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Sizer) {
         Efl.Io.Writer.can_write.set;
         Efl.Io.Closer.close;
         Efl.Io.Closer.closed.get;
+        Efl.Io.Closer.close_on_exec;
+        Efl.Io.Closer.close_on_destructor;
         Efl.Io.Sizer.resize;
         Efl.Io.Sizer.size.get;
     }
index 002f3c6..a44be53 100644 (file)
@@ -49,6 +49,10 @@ typedef struct _Efl_Net_Dialer_Tcp_Data
 EOLIAN static void
 _efl_net_dialer_tcp_efl_object_destructor(Eo *o, Efl_Net_Dialer_Tcp_Data *pd)
 {
+   if (efl_io_closer_close_on_destructor_get(o) &&
+       (!efl_io_closer_closed_get(o)))
+     efl_io_closer_close(o);
+
    if (pd->connect.thread)
      {
         ecore_thread_cancel(pd->connect.thread);
@@ -115,7 +119,7 @@ _efl_net_dialer_tcp_connected(void *data, const struct sockaddr *addr EINA_UNUSE
                                                   addrinfo->ai_addrlen,
                                                   SOCK_STREAM,
                                                   IPPROTO_TCP,
-                                                  efl_net_socket_fd_close_on_exec_get(o),
+                                                  efl_io_closer_close_on_exec_get(o),
                                                   _efl_net_dialer_tcp_connected,
                                                   o);
 }
@@ -148,7 +152,7 @@ _efl_net_dialer_tcp_connect(Eo *o, Efl_Net_Dialer_Tcp_Data *pd)
                                                   addrinfo->ai_addrlen,
                                                   SOCK_STREAM,
                                                   IPPROTO_TCP,
-                                                  efl_net_socket_fd_close_on_exec_get(o),
+                                                  efl_io_closer_close_on_exec_get(o),
                                                   _efl_net_dialer_tcp_connected,
                                                   o);
  end:
index 8364079..49d541e 100644 (file)
@@ -953,8 +953,6 @@ _efl_net_dialer_websocket_efl_object_destructor(Eo *o, Efl_Net_Dialer_Websocket_
         pd->close_timer = NULL;
      }
 
-   if (!efl_io_closer_closed_get(pd->http))
-     efl_io_closer_close(pd->http);
    efl_del(pd->http);
    pd->http = NULL;
 
@@ -1355,6 +1353,30 @@ _efl_net_dialer_websocket_efl_io_closer_closed_get(Eo *o EINA_UNUSED, Efl_Net_Di
    return pd->close_requested || efl_io_closer_closed_get(pd->http);
 }
 
+EOLIAN static Eina_Bool
+_efl_net_dialer_websocket_efl_io_closer_close_on_exec_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Websocket_Data *pd, Eina_Bool close_on_exec)
+{
+   return efl_io_closer_close_on_exec_set(pd->http, close_on_exec);
+}
+
+EOLIAN static Eina_Bool
+_efl_net_dialer_websocket_efl_io_closer_close_on_exec_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Websocket_Data *pd)
+{
+   return efl_io_closer_close_on_exec_get(pd->http);
+}
+
+EOLIAN static void
+_efl_net_dialer_websocket_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Websocket_Data *pd, Eina_Bool close_on_destructor)
+{
+   efl_io_closer_close_on_destructor_set(pd->http, close_on_destructor);
+}
+
+EOLIAN static Eina_Bool
+_efl_net_dialer_websocket_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Websocket_Data *pd)
+{
+   return efl_io_closer_close_on_destructor_get(pd->http);
+}
+
 EOLIAN static void
 _efl_net_dialer_websocket_streaming_mode_set(Eo *o, Efl_Net_Dialer_Websocket_Data *pd, Efl_Net_Dialer_Websocket_Streaming_Mode streaming_mode)
 {
index f096555..60b4530 100644 (file)
@@ -305,5 +305,7 @@ class Efl.Net.Dialer.Websocket (Efl.Loop_User, Efl.Net.Dialer) {
         Efl.Io.Writer.can_write.set;
         Efl.Io.Closer.close;
         Efl.Io.Closer.closed.get;
+        Efl.Io.Closer.close_on_exec;
+        Efl.Io.Closer.close_on_destructor;
     }
 }
index d469e3e..7b082e6 100644 (file)
@@ -26,7 +26,7 @@ class Efl.Net.Server.Fd (Efl.Loop.Fd, Efl.Net.Server) {
 
               Children socket will inherit the server's setting by
               default. One can change the behavior using each instance
-              @Efl.Net.Socket.Fd.close_on_exec.set.
+              @Efl.Io.Closer.close_on_exec.set.
             ]]
             get { }
             set {
index 9b556f5..ab39d60 100644 (file)
@@ -162,6 +162,8 @@ _efl_net_server_tcp_efl_net_server_fd_client_add(Eo *o, void *pd EINA_UNUSED, in
 {
    Eo *client = efl_add(EFL_NET_SOCKET_TCP_CLASS, o,
                         efl_event_callback_array_add(efl_added, _efl_net_server_tcp_client_cbs(), o),
+                        efl_io_closer_close_on_exec_set(efl_added, efl_net_server_fd_close_on_exec_get(o)),
+                        efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE),
                         efl_loop_fd_set(efl_added, client_fd));
    if (!client)
      {
@@ -177,7 +179,7 @@ _efl_net_server_tcp_efl_net_server_fd_client_add(Eo *o, void *pd EINA_UNUSED, in
      {
         DBG("client %s was not handled, closing it...",
             efl_net_socket_address_remote_get(client));
-        efl_io_closer_close(client);
+        efl_del(client);
      }
 }
 
index 339e7ef..f48736b 100644 (file)
@@ -31,7 +31,6 @@ typedef struct _Efl_Net_Socket_Fd_Data
    Eina_Stringshare *address_local;
    Eina_Stringshare *address_remote;
    int family;
-   Eina_Bool close_on_exec;
 } Efl_Net_Socket_Fd_Data;
 
 static void
@@ -73,12 +72,21 @@ EOLIAN static Efl_Object *
 _efl_net_socket_fd_efl_object_constructor(Eo *o, Efl_Net_Socket_Fd_Data *pd EINA_UNUSED)
 {
    pd->family = AF_UNSPEC;
-   return efl_constructor(efl_super(o, MY_CLASS));
+   o = efl_constructor(efl_super(o, MY_CLASS));
+
+   efl_io_closer_close_on_exec_set(o, EINA_TRUE);
+   efl_io_closer_close_on_destructor_set(o, EINA_TRUE);
+
+   return o;
 }
 
 EOLIAN static void
 _efl_net_socket_fd_efl_object_destructor(Eo *o, Efl_Net_Socket_Fd_Data *pd)
 {
+   if (efl_io_closer_close_on_destructor_get(o) &&
+       (!efl_io_closer_closed_get(o)))
+     efl_io_closer_close(o);
+
    efl_destructor(efl_super(o, MY_CLASS));
 
    eina_stringshare_replace(&pd->address_local, NULL);
@@ -88,12 +96,13 @@ _efl_net_socket_fd_efl_object_destructor(Eo *o, Efl_Net_Socket_Fd_Data *pd)
 static void
 _efl_net_socket_fd_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, int fd)
 {
+   Eina_Bool close_on_exec = efl_io_closer_close_on_exec_get(o); /* get cached value, otherwise will query from set fd */
    efl_io_reader_fd_reader_fd_set(o, fd);
    efl_io_writer_fd_writer_fd_set(o, fd);
    efl_io_closer_fd_closer_fd_set(o, fd);
 
    /* apply postponed values */
-   efl_net_socket_fd_close_on_exec_set(o, pd->close_on_exec);
+   efl_io_closer_close_on_exec_set(o, close_on_exec);
    if (pd->family == AF_UNSPEC)
      {
         ERR("efl_loop_fd_set() must be called after efl_net_server_fd_family_set()");
@@ -261,68 +270,6 @@ _efl_net_socket_fd_efl_net_socket_address_remote_get(Eo *o EINA_UNUSED, Efl_Net_
    return pd->address_remote;
 }
 
-EOLIAN static Eina_Bool
-_efl_net_socket_fd_close_on_exec_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, Eina_Bool close_on_exec)
-{
-#ifdef _WIN32
-   DBG("close on exec is not supported on windows");
-   pd->close_on_exec = close_on_exec;
-   return EINA_FALSE;
-#else
-   int flags, fd;
-
-   pd->close_on_exec = close_on_exec;
-
-   fd = efl_loop_fd_get(o);
-   if (fd < 0) return EINA_TRUE; /* postpone until fd_set() */
-
-   flags = fcntl(fd, F_GETFD);
-   if (flags < 0)
-     {
-        ERR("fcntl(%d, F_GETFD): %s", fd, strerror(errno));
-        return EINA_FALSE;
-     }
-   if (close_on_exec)
-     flags |= FD_CLOEXEC;
-   else
-     flags &= (~FD_CLOEXEC);
-   if (fcntl(fd, F_SETFD, flags) < 0)
-     {
-        ERR("fcntl(%d, F_SETFD, %#x): %s", fd, flags, strerror(errno));
-        return EINA_FALSE;
-     }
-
-   return EINA_TRUE;
-#endif
-}
-
-EOLIAN static Eina_Bool
-_efl_net_socket_fd_close_on_exec_get(Eo *o, Efl_Net_Socket_Fd_Data *pd)
-{
-#ifdef _WIN32
-   DBG("close on exec is not supported on windows");
-   return pd->close_on_exec;
-#else
-   int flags, fd;
-
-   fd = efl_loop_fd_get(o);
-   if (fd < 0) return pd->close_on_exec;
-
-   /* if there is a fd, always query it directly as it may be modified
-    * elsewhere by nasty users.
-    */
-   flags = fcntl(fd, F_GETFD);
-   if (flags < 0)
-     {
-        ERR("fcntl(%d, F_GETFD): %s", fd, strerror(errno));
-        return EINA_FALSE;
-     }
-
-   pd->close_on_exec = !!(flags & FD_CLOEXEC); /* sync */
-   return pd->close_on_exec;
-#endif
-}
-
 EOLIAN static void
 _efl_net_socket_fd_family_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Fd_Data *pd, int family)
 {
index 4ce2bfa..167edbd 100644 (file)
@@ -4,6 +4,10 @@ class Efl.Net.Socket.Fd (Efl.Loop.Fd, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Efl.Io
       This is the common class and takes an existing FD, usually
       created by an dialer or server.
 
+      @Efl.Io.Closer.close_on_exec and
+      @Efl.Io.Closer.close_on_destructor are respected and default to
+      $true.
+
       @since 1.19
     ]]
 
@@ -23,17 +27,6 @@ class Efl.Net.Socket.Fd (Efl.Loop.Fd, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Efl.Io
                 family: int;
             }
         }
-
-        @property close_on_exec {
-            [[Controls Close-on-Exec() using FD_CLOEXEC]]
-            get { }
-            set {
-                return: bool (false); [[$true on success]]
-            }
-            values {
-                close_on_exec: bool;
-            }
-        }
     }
 
     implements {
index 45f3ef5..3393ad4 100644 (file)
@@ -317,6 +317,31 @@ _efl_io_buffer_efl_io_closer_closed_get(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *p
    return pd->closed;
 }
 
+EOLIAN static Eina_Bool
+_efl_io_buffer_efl_io_closer_close_on_exec_set(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *pd EINA_UNUSED, Eina_Bool close_on_exec)
+{
+   if (!close_on_exec) return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_efl_io_buffer_efl_io_closer_close_on_exec_get(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *pd EINA_UNUSED)
+{
+   return EINA_TRUE;
+}
+
+EOLIAN static void
+_efl_io_buffer_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *pd EINA_UNUSED, Eina_Bool close_on_destructor EINA_UNUSED)
+{
+}
+
+EOLIAN static Eina_Bool
+_efl_io_buffer_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *pd EINA_UNUSED)
+{
+   return EINA_TRUE;
+}
+
 EOLIAN static Eina_Error
 _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
 {
index 89bb92b..5c0423d 100644 (file)
@@ -119,6 +119,8 @@ class Efl.Io.Buffer (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Ef
         Efl.Io.Writer.can_write.set;
         Efl.Io.Closer.close;
         Efl.Io.Closer.closed.get;
+        Efl.Io.Closer.close_on_exec;
+        Efl.Io.Closer.close_on_destructor;
         Efl.Io.Sizer.resize;
         Efl.Io.Sizer.size.get;
         Efl.Io.Positioner.seek;
index 6a27b02..d54dff6 100644 (file)
@@ -41,6 +41,36 @@ mixin Efl.Io.Closer {
                 is_closed: bool;
             }
         }
+
+        @property close_on_exec {
+            [[If true will automatically close resources on exec() calls.
+
+              When using file descriptors this should set FD_CLOEXEC
+              so they are not inherited by the processes (children or
+              self) doing exec().
+            ]]
+            get @virtual_pure { }
+            set @virtual_pure {
+                [[If true, will close on exec() call.]]
+                return: bool; [[$true if could set, $false if not supported or failed.]]
+            }
+            values {
+                close_on_exec: bool;
+            }
+        }
+
+        @property close_on_destructor {
+            [[If true will automatically close() on object destructor.
+
+              If the object was deleted without close, this property
+              will state whenever it should be closed or not.
+            ]]
+            get @virtual_pure { }
+            set @virtual_pure { }
+            values {
+                close_on_destructor: bool;
+            }
+        }
     }
 
     events {
index a4dcf32..6a7400c 100644 (file)
@@ -427,4 +427,29 @@ _efl_io_queue_efl_io_closer_closed_get(Eo *o EINA_UNUSED, Efl_Io_Queue_Data *pd)
    return pd->closed;
 }
 
+EOLIAN static Eina_Bool
+_efl_io_queue_efl_io_closer_close_on_exec_set(Eo *o EINA_UNUSED, Efl_Io_Queue_Data *pd EINA_UNUSED, Eina_Bool close_on_exec)
+{
+   if (!close_on_exec) return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_efl_io_queue_efl_io_closer_close_on_exec_get(Eo *o EINA_UNUSED, Efl_Io_Queue_Data *pd EINA_UNUSED)
+{
+   return EINA_TRUE;
+}
+
+EOLIAN static void
+_efl_io_queue_efl_io_closer_close_on_destructor_set(Eo *o EINA_UNUSED, Efl_Io_Queue_Data *pd EINA_UNUSED, Eina_Bool close_on_destructor EINA_UNUSED)
+{
+}
+
+EOLIAN static Eina_Bool
+_efl_io_queue_efl_io_closer_close_on_destructor_get(Eo *o EINA_UNUSED, Efl_Io_Queue_Data *pd EINA_UNUSED)
+{
+   return EINA_TRUE;
+}
+
 #include "interfaces/efl_io_queue.eo.c"
index 9ce3f0a..59dfa62 100644 (file)
@@ -90,5 +90,7 @@ class Efl.Io.Queue (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer) {
         Efl.Io.Writer.can_write.set;
         Efl.Io.Closer.close;
         Efl.Io.Closer.closed.get;
+        Efl.Io.Closer.close_on_exec;
+        Efl.Io.Closer.close_on_destructor;
     }
 }