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;
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",

View 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"

View 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;
}
}

View 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"

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
@.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;
}
}

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
_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"

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) {
[[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;
}

View 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)
{

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.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;
}

View 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:

View 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)
{

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.Closer.close;
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
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 {

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,
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);
}
}

View 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)
{

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
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 {

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;
}
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)
{

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.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;

View 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 {

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;
}
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"

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