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.
This commit is contained in:
Gustavo Sverzut Barbieri 2016-09-12 12:23:29 -03:00
parent 7c2671b1f7
commit ea7bc821d5
21 changed files with 396 additions and 94 deletions

View File

@ -58,8 +58,7 @@ _echo_copier_done(void *data EINA_UNUSED, const Efl_Event *event)
{ {
Eo *copier = event->object; Eo *copier = event->object;
fprintf(stderr, "INFO: echo copier done, close and del %p\n", copier); fprintf(stderr, "INFO: echo copier done, close and del %p\n", copier);
efl_io_closer_close(copier); efl_del(copier); /* set to close_on_destructor, will auto close copier and client */
efl_del(copier);
} }
static void 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", fprintf(stderr, "ERROR: echo copier %p failed %d, close and del.\n",
copier, *perr); copier, *perr);
efl_io_closer_close(copier);
efl_del(copier); efl_del(copier);
} }
@ -123,7 +121,7 @@ _send_recv_done(Send_Recv_Data *d, Eo *copier)
efl_del(copier); efl_del(copier);
if (d->send_copier || d->recv_copier) return; 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); _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), Eo *echo_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client),
efl_io_copier_source_set(efl_added, client), efl_io_copier_source_set(efl_added, client),
efl_io_copier_destination_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", 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), 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_source_set(efl_added, send_buffer),
efl_io_copier_destination_set(efl_added, client), 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", 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), d->recv_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client),
efl_io_copier_source_set(efl_added, client), efl_io_copier_source_set(efl_added, client),
efl_io_copier_destination_set(efl_added, recv_buffer), 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", fprintf(stderr, "INFO: using receiver buffer %p with copier %p for client %s\n",

View File

@ -5,6 +5,7 @@
#endif #endif
#include <Ecore.h> #include <Ecore.h>
#include <fcntl.h>
#include "ecore_private.h" #include "ecore_private.h"
#define MY_CLASS EFL_IO_CLOSER_FD_CLASS #define MY_CLASS EFL_IO_CLOSER_FD_CLASS
@ -12,6 +13,8 @@
typedef struct _Efl_Io_Closer_Fd_Data typedef struct _Efl_Io_Closer_Fd_Data
{ {
int fd; int fd;
Eina_Bool close_on_exec;
Eina_Bool close_on_destructor;
} Efl_Io_Closer_Fd_Data; } Efl_Io_Closer_Fd_Data;
EOLIAN static void 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; 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" #include "efl_io_closer_fd.eo.c"

View File

@ -17,5 +17,7 @@ mixin Efl.Io.Closer.Fd (Efl.Io.Closer) {
implements { implements {
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
} }
} }

View File

@ -23,6 +23,8 @@ typedef struct _Efl_Io_Copier_Data
} progress; } progress;
Eina_Bool closed; Eina_Bool closed;
Eina_Bool done; Eina_Bool done;
Eina_Bool close_on_exec;
Eina_Bool close_on_destructor;
} Efl_Io_Copier_Data; } Efl_Io_Copier_Data;
static void _efl_io_copier_write(Eo *o, Efl_Io_Copier_Data *pd); 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)) 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_event_callback_add(pd->source, EFL_IO_CLOSER_EVENT_CLOSED,
_efl_io_copier_source_closed, o); _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)) 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_event_callback_add(pd->destination, EFL_IO_CLOSER_EVENT_CLOSED,
_efl_io_copier_destination_closed, o); _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) _efl_io_copier_efl_object_constructor(Eo *o, Efl_Io_Copier_Data *pd)
{ {
pd->buf = eina_binbuf_new(); 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); 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); _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_source_set(o, NULL);
efl_io_copier_destination_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" #include "efl_io_copier.eo.c"

View 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 If @Efl.Io.Closer.close is called, then it will be called on
@.source and @.destination if they implement those interfaces. @.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 @since 1.19
]] ]]
@ -108,5 +112,7 @@ class Efl.Io.Copier (Efl.Loop_User, Efl.Io.Closer) {
Efl.Object.finalize; Efl.Object.finalize;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
} }
} }

View 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 EOLIAN static void
_efl_io_file_flags_set(Eo *o, Efl_Io_File_Data *pd, uint32_t flags) _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)); EINA_SAFETY_ON_TRUE_RETURN(efl_finalized_get(o));
pd->flags = flags; 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 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; 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 EOLIAN static void
_efl_io_file_efl_object_destructor(Eo *o, Efl_Io_File_Data *pd) _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_io_closer_close(o);
efl_destructor(efl_super(o, MY_CLASS)); 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; 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" #include "efl_io_file.eo.c"

View 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) { 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) [[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 @since 1.19
]] ]]
methods { methods {
@property flags { @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 { get {
} }
@ -36,6 +46,7 @@ class Efl.Io.File (Efl.Loop.Fd, Efl.File, Efl.Io.Reader.Fd, Efl.Io.Writer.Fd, Ef
} }
implements { implements {
Efl.Object.constructor;
Efl.Object.destructor; Efl.Object.destructor;
Efl.Object.finalize; Efl.Object.finalize;
Efl.Loop.Fd.fd_file.set; 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.Reader.read;
Efl.Io.Writer.write; Efl.Io.Writer.write;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.close_on_exec.set;
Efl.Io.Sizer.resize; Efl.Io.Sizer.resize;
Efl.Io.Positioner.seek; Efl.Io.Positioner.seek;
} }

View File

@ -24,6 +24,7 @@
#include "ecore_con_url_curl.h" #include "ecore_con_url_curl.h"
#include <ctype.h> #include <ctype.h>
#include <fcntl.h>
/* improve usage of lazy-loaded library in _c-> */ /* improve usage of lazy-loaded library in _c-> */
#define curl_easy_strerror(...) _c->curl_easy_strerror(__VA_ARGS__) #define curl_easy_strerror(...) _c->curl_easy_strerror(__VA_ARGS__)
@ -210,6 +211,8 @@ typedef struct
uint8_t pause; uint8_t pause;
Eina_Bool connected; Eina_Bool connected;
Eina_Bool closed; Eina_Bool closed;
Eina_Bool close_on_exec;
Eina_Bool close_on_destructor;
Eina_Bool eos; Eina_Bool eos;
Eina_Bool can_read; Eina_Bool can_read;
Eina_Bool can_write; Eina_Bool can_write;
@ -1096,7 +1099,7 @@ _efl_net_dialer_http_socket_open(void *data, curlsocktype purpose EINA_UNUSED, s
Eo *o = data; Eo *o = data;
Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS); 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) if (pd->fd < 0)
ERR("could not create curl socket family=%d, type=%d, protocol=%d", ERR("could not create curl socket family=%d, type=%d, protocol=%d",
addr->family, addr->socktype, addr->protocol); 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; pd->pending_close = NULL;
efl_io_closer_close(o); 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_io_closer_close(o);
efl_net_dialer_http_response_headers_clear(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); 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 EOLIAN static Eina_Error
_efl_net_dialer_http_efl_io_sizer_resize(Eo *o, Efl_Net_Dialer_Http_Data *pd, uint64_t size) _efl_net_dialer_http_efl_io_sizer_resize(Eo *o, Efl_Net_Dialer_Http_Data *pd, uint64_t size)
{ {

View 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.Writer.can_write.set;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
Efl.Io.Sizer.resize; Efl.Io.Sizer.resize;
Efl.Io.Sizer.size.get; Efl.Io.Sizer.size.get;
} }

View File

@ -49,6 +49,10 @@ typedef struct _Efl_Net_Dialer_Tcp_Data
EOLIAN static void EOLIAN static void
_efl_net_dialer_tcp_efl_object_destructor(Eo *o, Efl_Net_Dialer_Tcp_Data *pd) _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) if (pd->connect.thread)
{ {
ecore_thread_cancel(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, addrinfo->ai_addrlen,
SOCK_STREAM, SOCK_STREAM,
IPPROTO_TCP, IPPROTO_TCP,
efl_net_socket_fd_close_on_exec_get(o), efl_io_closer_close_on_exec_get(o),
_efl_net_dialer_tcp_connected, _efl_net_dialer_tcp_connected,
o); o);
} }
@ -148,7 +152,7 @@ _efl_net_dialer_tcp_connect(Eo *o, Efl_Net_Dialer_Tcp_Data *pd)
addrinfo->ai_addrlen, addrinfo->ai_addrlen,
SOCK_STREAM, SOCK_STREAM,
IPPROTO_TCP, IPPROTO_TCP,
efl_net_socket_fd_close_on_exec_get(o), efl_io_closer_close_on_exec_get(o),
_efl_net_dialer_tcp_connected, _efl_net_dialer_tcp_connected,
o); o);
end: end:

View File

@ -953,8 +953,6 @@ _efl_net_dialer_websocket_efl_object_destructor(Eo *o, Efl_Net_Dialer_Websocket_
pd->close_timer = NULL; pd->close_timer = NULL;
} }
if (!efl_io_closer_closed_get(pd->http))
efl_io_closer_close(pd->http);
efl_del(pd->http); efl_del(pd->http);
pd->http = NULL; 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); 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 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) _efl_net_dialer_websocket_streaming_mode_set(Eo *o, Efl_Net_Dialer_Websocket_Data *pd, Efl_Net_Dialer_Websocket_Streaming_Mode streaming_mode)
{ {

View File

@ -305,5 +305,7 @@ class Efl.Net.Dialer.Websocket (Efl.Loop_User, Efl.Net.Dialer) {
Efl.Io.Writer.can_write.set; Efl.Io.Writer.can_write.set;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
} }
} }

View 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 Children socket will inherit the server's setting by
default. One can change the behavior using each instance 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 { } get { }
set { set {

View 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, 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_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)); efl_loop_fd_set(efl_added, client_fd));
if (!client) 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...", DBG("client %s was not handled, closing it...",
efl_net_socket_address_remote_get(client)); efl_net_socket_address_remote_get(client));
efl_io_closer_close(client); efl_del(client);
} }
} }

View File

@ -31,7 +31,6 @@ typedef struct _Efl_Net_Socket_Fd_Data
Eina_Stringshare *address_local; Eina_Stringshare *address_local;
Eina_Stringshare *address_remote; Eina_Stringshare *address_remote;
int family; int family;
Eina_Bool close_on_exec;
} Efl_Net_Socket_Fd_Data; } Efl_Net_Socket_Fd_Data;
static void 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) _efl_net_socket_fd_efl_object_constructor(Eo *o, Efl_Net_Socket_Fd_Data *pd EINA_UNUSED)
{ {
pd->family = AF_UNSPEC; 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 EOLIAN static void
_efl_net_socket_fd_efl_object_destructor(Eo *o, Efl_Net_Socket_Fd_Data *pd) _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)); efl_destructor(efl_super(o, MY_CLASS));
eina_stringshare_replace(&pd->address_local, NULL); 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 static void
_efl_net_socket_fd_set(Eo *o, Efl_Net_Socket_Fd_Data *pd, int fd) _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_reader_fd_reader_fd_set(o, fd);
efl_io_writer_fd_writer_fd_set(o, fd); efl_io_writer_fd_writer_fd_set(o, fd);
efl_io_closer_fd_closer_fd_set(o, fd); efl_io_closer_fd_closer_fd_set(o, fd);
/* apply postponed values */ /* 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) if (pd->family == AF_UNSPEC)
{ {
ERR("efl_loop_fd_set() must be called after efl_net_server_fd_family_set()"); 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; 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 EOLIAN static void
_efl_net_socket_fd_family_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Fd_Data *pd, int family) _efl_net_socket_fd_family_set(Eo *o EINA_UNUSED, Efl_Net_Socket_Fd_Data *pd, int family)
{ {

View 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 This is the common class and takes an existing FD, usually
created by an dialer or server. 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 @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; 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 { implements {

View 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; 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 EOLIAN static Eina_Error
_efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size) _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
{ {

View 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.Writer.can_write.set;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
Efl.Io.Sizer.resize; Efl.Io.Sizer.resize;
Efl.Io.Sizer.size.get; Efl.Io.Sizer.size.get;
Efl.Io.Positioner.seek; Efl.Io.Positioner.seek;

View File

@ -41,6 +41,36 @@ mixin Efl.Io.Closer {
is_closed: bool; 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 { events {

View 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; 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" #include "interfaces/efl_io_queue.eo.c"

View 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.Writer.can_write.set;
Efl.Io.Closer.close; Efl.Io.Closer.close;
Efl.Io.Closer.closed.get; Efl.Io.Closer.closed.get;
Efl.Io.Closer.close_on_exec;
Efl.Io.Closer.close_on_destructor;
} }
} }