ecore_main: Add ECORE_FD_ALWAYS flag

Summary:
This allows an fd handler to be called after select exits unconditionally.

Our wayland client code needs this to be thread safe, as it needs to
call prepare_read before entering select, and then either read or
cancel_read after select.

Reviewers: cedric

Reviewed By: cedric

Subscribers: zmike, cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7914
This commit is contained in:
Derek Foreman 2019-02-12 13:51:02 -05:00 committed by Christopher Michael
parent 27e101da4b
commit b5e90ebe0d
3 changed files with 43 additions and 13 deletions

View File

@ -1388,7 +1388,13 @@ enum _Ecore_Fd_Handler_Flags
{ {
ECORE_FD_READ = 1, /**< Fd Read mask */ ECORE_FD_READ = 1, /**< Fd Read mask */
ECORE_FD_WRITE = 2, /**< Fd Write mask */ ECORE_FD_WRITE = 2, /**< Fd Write mask */
ECORE_FD_ERROR = 4 /**< Fd Error mask */ ECORE_FD_ERROR = 4, /**< Fd Error mask */
/* ECORE_FD_ALWAYS is intended to fix a problem with wayland
* and threads. It causes the fd handler to be called
* in any state, so wayland libs can call read_cancel
* if nothing is available to read. Everyone else should
* stay away. */
ECORE_FD_ALWAYS = 8, /**< Fd Always mask - DO NOT USE! */
}; };
typedef enum _Ecore_Fd_Handler_Flags Ecore_Fd_Handler_Flags; typedef enum _Ecore_Fd_Handler_Flags Ecore_Fd_Handler_Flags;

View File

@ -248,7 +248,7 @@ _ecore_try_add_to_call_list(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, Ecore_Fd_Han
DBG("next_ready"); DBG("next_ready");
return; return;
} }
if (fdh->read_active || fdh->write_active || fdh->error_active) if (fdh->read_active || fdh->write_active || fdh->error_active || (fdh->flags & ECORE_FD_ALWAYS))
{ {
DBG("added"); DBG("added");
// make sure next_ready is non-null by pointing to ourselves // make sure next_ready is non-null by pointing to ourselves
@ -583,6 +583,10 @@ _ecore_main_fdh_epoll_mark_active(Eo *obj, Efl_Loop_Data *pd)
fdh->write_active = EINA_TRUE; fdh->write_active = EINA_TRUE;
fdh->error_active = EINA_TRUE; fdh->error_active = EINA_TRUE;
} }
/* We'll add this one anyway outside this function,
don't want it twice */
if (fdh->flags & ECORE_FD_ALWAYS)
continue;
_ecore_try_add_to_call_list(obj, pd, fdh); _ecore_try_add_to_call_list(obj, pd, fdh);
} }
@ -1357,6 +1361,9 @@ _ecore_main_fd_handler_add(Eo *obj,
if (is_file) if (is_file)
pd->file_fd_handlers = eina_list_append pd->file_fd_handlers = eina_list_append
(pd->file_fd_handlers, fdh); (pd->file_fd_handlers, fdh);
if (fdh->flags & ECORE_FD_ALWAYS)
pd->always_fd_handlers = eina_list_append
(pd->always_fd_handlers, fdh);
pd->fd_handlers = (Ecore_Fd_Handler *) pd->fd_handlers = (Ecore_Fd_Handler *)
eina_inlist_append(EINA_INLIST_GET(pd->fd_handlers), eina_inlist_append(EINA_INLIST_GET(pd->fd_handlers),
EINA_INLIST_GET(fdh)); EINA_INLIST_GET(fdh));
@ -1664,6 +1671,9 @@ _ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd)
if (pd->file_fd_handlers) if (pd->file_fd_handlers)
pd->file_fd_handlers = pd->file_fd_handlers =
eina_list_free(pd->file_fd_handlers); eina_list_free(pd->file_fd_handlers);
if (pd->always_fd_handlers)
pd->always_fd_handlers =
eina_list_free(pd->always_fd_handlers);
if (pd->fd_handlers_to_delete) if (pd->fd_handlers_to_delete)
pd->fd_handlers_to_delete = pd->fd_handlers_to_delete =
eina_list_free(pd->fd_handlers_to_delete); eina_list_free(pd->fd_handlers_to_delete);
@ -1741,7 +1751,7 @@ _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
fd_set rfds, wfds, exfds; fd_set rfds, wfds, exfds;
Ecore_Fd_Handler *fdh; Ecore_Fd_Handler *fdh;
Eina_List *l; Eina_List *l;
int max_fd, ret; int max_fd, ret, outval;
#ifndef _WIN32 #ifndef _WIN32
int err_no; int err_no;
#endif #endif
@ -1785,17 +1795,17 @@ _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
{ {
if (!fdh->delete_me) if (!fdh->delete_me)
{ {
if (fdh->flags & ECORE_FD_READ) if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &rfds); FD_SET(fdh->fd, &rfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
} }
if (fdh->flags & ECORE_FD_WRITE) if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &wfds); FD_SET(fdh->fd, &wfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
} }
if (fdh->flags & ECORE_FD_ERROR) if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &exfds); FD_SET(fdh->fd, &exfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
@ -1815,17 +1825,17 @@ _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
{ {
if (!fdh->delete_me) if (!fdh->delete_me)
{ {
if (fdh->flags & ECORE_FD_READ) if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &rfds); FD_SET(fdh->fd, &rfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
} }
if (fdh->flags & ECORE_FD_WRITE) if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &wfds); FD_SET(fdh->fd, &wfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
} }
if (fdh->flags & ECORE_FD_ERROR) if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
{ {
FD_SET(fdh->fd, &exfds); FD_SET(fdh->fd, &exfds);
if (fdh->fd > max_fd) max_fd = fdh->fd; if (fdh->fd > max_fd) max_fd = fdh->fd;
@ -1851,7 +1861,11 @@ _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
if (ret < 0) if (ret < 0)
{ {
#ifndef _WIN32 #ifndef _WIN32
if (err_no == EINTR) return -1; if (err_no == EINTR)
{
outval = -1;
goto BAIL;
}
else if (err_no == EBADF) _ecore_main_fd_handlers_bads_rem(obj, pd); else if (err_no == EBADF) _ecore_main_fd_handlers_bads_rem(obj, pd);
#endif #endif
} }
@ -1894,9 +1908,15 @@ _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
#ifdef _WIN32 #ifdef _WIN32
_ecore_main_win32_handlers_cleanup(obj, pd); _ecore_main_win32_handlers_cleanup(obj, pd);
#endif #endif
return 1; outval = 1;
goto BAIL;
} }
return 0; outval = 0;
BAIL:
EINA_LIST_FOREACH(pd->always_fd_handlers, l, fdh)
_ecore_try_add_to_call_list(obj, pd, fdh);
return outval;
} }
#endif #endif
@ -2017,6 +2037,8 @@ _ecore_main_fd_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
EINA_INLIST_GET(fdh)); EINA_INLIST_GET(fdh));
if (fdh->file) if (fdh->file)
pd->file_fd_handlers = eina_list_remove(pd->file_fd_handlers, fdh); pd->file_fd_handlers = eina_list_remove(pd->file_fd_handlers, fdh);
if (fdh->flags & ECORE_FD_ALWAYS)
pd->always_fd_handlers = eina_list_remove(pd->always_fd_handlers, fdh);
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
ecore_fd_handler_mp_free(fdh); ecore_fd_handler_mp_free(fdh);
pd->fd_handlers_to_delete = eina_list_remove_list pd->fd_handlers_to_delete = eina_list_remove_list
@ -2074,7 +2096,8 @@ _ecore_main_fd_handlers_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
{ {
if ((fdh->read_active) || if ((fdh->read_active) ||
(fdh->write_active) || (fdh->write_active) ||
(fdh->error_active)) (fdh->error_active) ||
(fdh->flags & ECORE_FD_ALWAYS))
{ {
fdh->references++; fdh->references++;
if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh)) if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh))

View File

@ -138,6 +138,7 @@ struct _Efl_Loop_Data
Ecore_Fd_Handler *fd_handlers; Ecore_Fd_Handler *fd_handlers;
Eina_List *fd_handlers_with_prep; Eina_List *fd_handlers_with_prep;
Eina_List *file_fd_handlers; Eina_List *file_fd_handlers;
Eina_List *always_fd_handlers;
Eina_List *fd_handlers_with_buffer; Eina_List *fd_handlers_with_buffer;
Eina_List *fd_handlers_to_delete; Eina_List *fd_handlers_to_delete;
Ecore_Fd_Handler *fd_handlers_to_call; Ecore_Fd_Handler *fd_handlers_to_call;