add ecore_main_fd_handler_file_add() for use with regular files.

epoll does not handle reading from files since it is only a mechanism for determining whether a fd is ready for read/write/error, and regular files are always ready. as a result, we must select on them explicitly without adding to the epoll fd

I realize that this is a feature freeze, but it's rather non-invasive and this is an absolute must-have to fix mounting for e17 so...sorry!


SVN revision: 74741
This commit is contained in:
Mike Blumenkrantz 2012-08-01 14:37:24 +00:00
parent 15a9aa0950
commit 3fc5ceadd7
2 changed files with 113 additions and 8 deletions

View File

@ -1085,6 +1085,26 @@ typedef Eina_Bool (*Ecore_Win32_Handle_Cb)(void *data, Ecore_Win32_Handler *wh);
*
*/
EAPI Ecore_Fd_Handler *ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func, const void *data, Ecore_Fd_Cb buf_func, const void *buf_data);
/**
* @brief Adds a callback for activity on the given file descriptor.
*
* @param fd The file descriptor to watch.
* @param flags To monitor it for reading use @c ECORE_FD_READ, for writing @c
* ECORE_FD_WRITE, and for error @c ECORE_FD_ERROR. Values by |(ored).
* @param func The callback function.
* @param data The data to pass to the callback.
* @param buf_func The function to call to check if any data has been buffered
* and already read from the fd. May be @c NULL.
* @param buf_data The data to pass to the @p buf_func function.
* @return A fd handler handle on success, @c NULL otherwise.
*
* This function is identical to ecore_main_fd_handler_add, except that it supports regular files.
*
* @since 1.7
*/
EAPI Ecore_Fd_Handler *ecore_main_fd_handler_file_add(int fd, Ecore_Fd_Handler_Flags flags, Ecore_Fd_Cb func, const void *data, Ecore_Fd_Cb buf_func, const void *buf_data);
/**
* @brief Set the prepare callback with data for a given #Ecore_Fd_Handler
*

View File

@ -163,6 +163,7 @@ struct _Ecore_Fd_Handler
Eina_Bool write_active : 1;
Eina_Bool error_active : 1;
Eina_Bool delete_me : 1;
Eina_Bool file : 1;
#if defined(USE_G_MAIN_LOOP)
GPollFD gfd;
#endif
@ -213,6 +214,7 @@ static int do_quit = 0;
static Ecore_Fd_Handler *fd_handlers = NULL;
static Ecore_Fd_Handler *fd_handler_current = NULL;
static Eina_List *fd_handlers_with_prep = NULL;
static Eina_List *file_fd_handlers = NULL;
static Eina_List *fd_handlers_with_buffer = NULL;
static Eina_List *fd_handlers_to_delete = NULL;
@ -326,7 +328,7 @@ _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh)
int events = 0;
if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN;
if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT;
if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR;
if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR | EPOLLPRI;
return events;
}
@ -348,7 +350,7 @@ _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh)
{
int r = 0;
if (HAVE_EPOLL && epoll_fd >= 0)
if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
{
r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd,
_ecore_poll_events_from_fdh(fdh), fdh);
@ -369,7 +371,7 @@ _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh)
static inline void
_ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh)
{
if (HAVE_EPOLL && epoll_fd >= 0)
if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
{
struct epoll_event ev;
int efd = _ecore_get_epoll_fd();
@ -408,7 +410,7 @@ static inline int
_ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh)
{
int r = 0;
if (HAVE_EPOLL && epoll_fd >= 0)
if ((!fdh->file) && HAVE_EPOLL && epoll_fd >= 0)
{
struct epoll_event ev;
int efd = _ecore_get_epoll_fd();
@ -1041,6 +1043,56 @@ unlock:
return fdh;
}
EAPI Ecore_Fd_Handler *
ecore_main_fd_handler_file_add(int fd,
Ecore_Fd_Handler_Flags flags,
Ecore_Fd_Cb func,
const void *data,
Ecore_Fd_Cb buf_func,
const void *buf_data)
{
Ecore_Fd_Handler *fdh = NULL;
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
_ecore_lock();
if ((fd < 0) || (flags == 0) || (!func)) goto unlock;
fdh = ecore_fd_handler_calloc(1);
if (!fdh) goto unlock;
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
fdh->next_ready = NULL;
fdh->fd = fd;
fdh->flags = flags;
fdh->file = EINA_TRUE;
if (_ecore_main_fdh_poll_add(fdh) < 0)
{
int err = errno;
ERR("Failed to add poll on fd %d (errno = %d: %s)!", fd, err, strerror(err));
ecore_fd_handler_mp_free(fdh);
fdh = NULL;
goto unlock;
}
fdh->read_active = EINA_FALSE;
fdh->write_active = EINA_FALSE;
fdh->error_active = EINA_FALSE;
fdh->delete_me = EINA_FALSE;
fdh->func = func;
fdh->data = (void *)data;
fdh->buf_func = buf_func;
if (buf_func)
fd_handlers_with_buffer = eina_list_append(fd_handlers_with_buffer, fdh);
fdh->buf_data = (void *)buf_data;
fd_handlers = (Ecore_Fd_Handler *)
eina_inlist_append(EINA_INLIST_GET(fd_handlers),
EINA_INLIST_GET(fdh));
file_fd_handlers = eina_list_append(file_fd_handlers, fdh);
unlock:
_ecore_unlock();
return fdh;
}
#ifdef _WIN32
EAPI Ecore_Win32_Handler *
ecore_main_win32_handler_add(void *h,
@ -1243,6 +1295,8 @@ _ecore_main_shutdown(void)
fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep);
if (fd_handlers_to_delete)
fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete);
if (file_fd_handlers)
file_fd_handlers = eina_list_free(file_fd_handlers);
fd_handlers_to_call = NULL;
fd_handlers_to_call_current = NULL;
@ -1296,6 +1350,8 @@ _ecore_main_select(double timeout)
{
struct timeval tv, *t;
fd_set rfds, wfds, exfds;
Ecore_Fd_Handler *fdh;
Eina_List *l;
int max_fd;
int ret;
@ -1333,8 +1389,6 @@ _ecore_main_select(double timeout)
if (!HAVE_EPOLL || epoll_fd < 0)
{
Ecore_Fd_Handler *fdh;
EINA_INLIST_FOREACH(fd_handlers, fdh)
{
if (!fdh->delete_me)
@ -1363,7 +1417,26 @@ _ecore_main_select(double timeout)
max_fd = _ecore_get_epoll_fd();
FD_SET(max_fd, &rfds);
}
EINA_LIST_FOREACH(file_fd_handlers, l, fdh)
if (!fdh->delete_me)
{
if (fdh->flags & ECORE_FD_READ)
{
FD_SET(fdh->fd, &rfds);
if (fdh->fd > max_fd) max_fd = fdh->fd;
}
if (fdh->flags & ECORE_FD_WRITE)
{
FD_SET(fdh->fd, &wfds);
if (fdh->fd > max_fd) max_fd = fdh->fd;
}
if (fdh->flags & ECORE_FD_ERROR)
{
FD_SET(fdh->fd, &exfds);
if (fdh->fd > max_fd) max_fd = fdh->fd;
}
if (fdh->fd > max_fd) max_fd = fdh->fd;
}
if (_ecore_signal_count_get()) return -1;
_ecore_unlock();
@ -1401,7 +1474,17 @@ _ecore_main_select(double timeout)
}
}
}
EINA_LIST_FOREACH(file_fd_handlers, l, fdh)
if (!fdh->delete_me)
{
if (FD_ISSET(fdh->fd, &rfds))
fdh->read_active = EINA_TRUE;
if (FD_ISSET(fdh->fd, &wfds))
fdh->write_active = EINA_TRUE;
if (FD_ISSET(fdh->fd, &exfds))
fdh->error_active = EINA_TRUE;
_ecore_try_add_to_call_list(fdh);
}
_ecore_main_fd_handlers_cleanup();
#ifdef _WIN32
_ecore_main_win32_handlers_cleanup();
@ -1498,6 +1581,8 @@ _ecore_main_fd_handlers_cleanup(void)
fd_handlers_with_prep = eina_list_remove(fd_handlers_with_prep, fdh);
fd_handlers = (Ecore_Fd_Handler *)
eina_inlist_remove(EINA_INLIST_GET(fd_handlers), EINA_INLIST_GET(fdh));
if (fdh->file)
file_fd_handlers = eina_list_remove(file_fd_handlers, fdh);
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
ecore_fd_handler_mp_free(fdh);
fd_handlers_to_delete = eina_list_remove_list(fd_handlers_to_delete, l);