From ea7bc821d5a224962242954a14bdb23d5ddedfb6 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Mon, 12 Sep 2016 12:23:29 -0300 Subject: [PATCH] efl_io_closer: add close_on_exec and close_on_destructor properties. the purpose of these properties are to make it more uniform the handling of these auto-close behavior. --- src/examples/ecore/efl_net_server_example.c | 15 ++-- src/lib/ecore/efl_io_closer_fd.c | 82 +++++++++++++++++++ src/lib/ecore/efl_io_closer_fd.eo | 2 + src/lib/ecore/efl_io_copier.c | 52 ++++++++++++ src/lib/ecore/efl_io_copier.eo | 6 ++ src/lib/ecore/efl_io_file.c | 34 +++++++- src/lib/ecore/efl_io_file.eo | 16 +++- src/lib/ecore_con/efl_net_dialer_http.c | 63 +++++++++++++- src/lib/ecore_con/efl_net_dialer_http.eo | 2 + src/lib/ecore_con/efl_net_dialer_tcp.c | 8 +- src/lib/ecore_con/efl_net_dialer_websocket.c | 26 +++++- src/lib/ecore_con/efl_net_dialer_websocket.eo | 2 + src/lib/ecore_con/efl_net_server_fd.eo | 2 +- src/lib/ecore_con/efl_net_server_tcp.c | 4 +- src/lib/ecore_con/efl_net_socket_fd.c | 77 +++-------------- src/lib/ecore_con/efl_net_socket_fd.eo | 15 +--- src/lib/efl/interfaces/efl_io_buffer.c | 25 ++++++ src/lib/efl/interfaces/efl_io_buffer.eo | 2 + src/lib/efl/interfaces/efl_io_closer.eo | 30 +++++++ src/lib/efl/interfaces/efl_io_queue.c | 25 ++++++ src/lib/efl/interfaces/efl_io_queue.eo | 2 + 21 files changed, 396 insertions(+), 94 deletions(-) diff --git a/src/examples/ecore/efl_net_server_example.c b/src/examples/ecore/efl_net_server_example.c index 620a94e6e6..2ffcdeed28 100644 --- a/src/examples/ecore/efl_net_server_example.c +++ b/src/examples/ecore/efl_net_server_example.c @@ -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", diff --git a/src/lib/ecore/efl_io_closer_fd.c b/src/lib/ecore/efl_io_closer_fd.c index a0ad5eca2d..db2bcaa05b 100644 --- a/src/lib/ecore/efl_io_closer_fd.c +++ b/src/lib/ecore/efl_io_closer_fd.c @@ -5,6 +5,7 @@ #endif #include +#include #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" diff --git a/src/lib/ecore/efl_io_closer_fd.eo b/src/lib/ecore/efl_io_closer_fd.eo index 35f881b036..853f2b4562 100644 --- a/src/lib/ecore/efl_io_closer_fd.eo +++ b/src/lib/ecore/efl_io_closer_fd.eo @@ -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; } } diff --git a/src/lib/ecore/efl_io_copier.c b/src/lib/ecore/efl_io_copier.c index 457007d740..23e77ac5b5 100644 --- a/src/lib/ecore/efl_io_copier.c +++ b/src/lib/ecore/efl_io_copier.c @@ -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" diff --git a/src/lib/ecore/efl_io_copier.eo b/src/lib/ecore/efl_io_copier.eo index 4a14a0737b..28dcf8258e 100644 --- a/src/lib/ecore/efl_io_copier.eo +++ b/src/lib/ecore/efl_io_copier.eo @@ -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; } } diff --git a/src/lib/ecore/efl_io_file.c b/src/lib/ecore/efl_io_file.c index 40c0346f01..a5ec38f3b0 100644 --- a/src/lib/ecore/efl_io_file.c +++ b/src/lib/ecore/efl_io_file.c @@ -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" diff --git a/src/lib/ecore/efl_io_file.eo b/src/lib/ecore/efl_io_file.eo index 6139634ba9..841f173299 100644 --- a/src/lib/ecore/efl_io_file.eo +++ b/src/lib/ecore/efl_io_file.eo @@ -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; } diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index 31832f50ef..e1de2301cc 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -24,6 +24,7 @@ #include "ecore_con_url_curl.h" #include +#include /* 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) { diff --git a/src/lib/ecore_con/efl_net_dialer_http.eo b/src/lib/ecore_con/efl_net_dialer_http.eo index f1b42dd396..f7c439a79a 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.eo +++ b/src/lib/ecore_con/efl_net_dialer_http.eo @@ -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; } diff --git a/src/lib/ecore_con/efl_net_dialer_tcp.c b/src/lib/ecore_con/efl_net_dialer_tcp.c index 002f3c6293..a44be53ab1 100644 --- a/src/lib/ecore_con/efl_net_dialer_tcp.c +++ b/src/lib/ecore_con/efl_net_dialer_tcp.c @@ -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: diff --git a/src/lib/ecore_con/efl_net_dialer_websocket.c b/src/lib/ecore_con/efl_net_dialer_websocket.c index 8364079d03..49d541e323 100644 --- a/src/lib/ecore_con/efl_net_dialer_websocket.c +++ b/src/lib/ecore_con/efl_net_dialer_websocket.c @@ -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) { diff --git a/src/lib/ecore_con/efl_net_dialer_websocket.eo b/src/lib/ecore_con/efl_net_dialer_websocket.eo index f0965556e9..60b4530494 100644 --- a/src/lib/ecore_con/efl_net_dialer_websocket.eo +++ b/src/lib/ecore_con/efl_net_dialer_websocket.eo @@ -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; } } diff --git a/src/lib/ecore_con/efl_net_server_fd.eo b/src/lib/ecore_con/efl_net_server_fd.eo index d469e3eba6..7b082e6075 100644 --- a/src/lib/ecore_con/efl_net_server_fd.eo +++ b/src/lib/ecore_con/efl_net_server_fd.eo @@ -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 { diff --git a/src/lib/ecore_con/efl_net_server_tcp.c b/src/lib/ecore_con/efl_net_server_tcp.c index 9b556f5eef..ab39d609c0 100644 --- a/src/lib/ecore_con/efl_net_server_tcp.c +++ b/src/lib/ecore_con/efl_net_server_tcp.c @@ -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); } } diff --git a/src/lib/ecore_con/efl_net_socket_fd.c b/src/lib/ecore_con/efl_net_socket_fd.c index 339e7efdfb..f48736b1ef 100644 --- a/src/lib/ecore_con/efl_net_socket_fd.c +++ b/src/lib/ecore_con/efl_net_socket_fd.c @@ -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) { diff --git a/src/lib/ecore_con/efl_net_socket_fd.eo b/src/lib/ecore_con/efl_net_socket_fd.eo index 4ce2bfa54d..167edbd920 100644 --- a/src/lib/ecore_con/efl_net_socket_fd.eo +++ b/src/lib/ecore_con/efl_net_socket_fd.eo @@ -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 { diff --git a/src/lib/efl/interfaces/efl_io_buffer.c b/src/lib/efl/interfaces/efl_io_buffer.c index 45f3ef59ad..3393ad45e0 100644 --- a/src/lib/efl/interfaces/efl_io_buffer.c +++ b/src/lib/efl/interfaces/efl_io_buffer.c @@ -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) { diff --git a/src/lib/efl/interfaces/efl_io_buffer.eo b/src/lib/efl/interfaces/efl_io_buffer.eo index 89bb92b71c..5c0423d524 100644 --- a/src/lib/efl/interfaces/efl_io_buffer.eo +++ b/src/lib/efl/interfaces/efl_io_buffer.eo @@ -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; diff --git a/src/lib/efl/interfaces/efl_io_closer.eo b/src/lib/efl/interfaces/efl_io_closer.eo index 6a27b02a9b..d54dff6a28 100644 --- a/src/lib/efl/interfaces/efl_io_closer.eo +++ b/src/lib/efl/interfaces/efl_io_closer.eo @@ -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 { diff --git a/src/lib/efl/interfaces/efl_io_queue.c b/src/lib/efl/interfaces/efl_io_queue.c index a4dcf3216b..6a7400ccf6 100644 --- a/src/lib/efl/interfaces/efl_io_queue.c +++ b/src/lib/efl/interfaces/efl_io_queue.c @@ -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" diff --git a/src/lib/efl/interfaces/efl_io_queue.eo b/src/lib/efl/interfaces/efl_io_queue.eo index 9ce3f0aa40..59dfa6225a 100644 --- a/src/lib/efl/interfaces/efl_io_queue.eo +++ b/src/lib/efl/interfaces/efl_io_queue.eo @@ -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; } }