efl_io_model: next try to fix this race condition

what is happening is that a file gets announced through eio_model
listing code, at this point of time, the monitor does not yet know about
the file. If the file now gets deleted between the annoncing and the
learning of the file from the monitor, then the file got an ADD event,
but no DEL event. Which is a bug.

With this commit there is a new API which asks the monitor if the file
already has the knowledge about the files existance, or not. A few
monitors like win32 inotify or cocoa do not have context about the file
directly, if the OS is now having the same bug, then we are again in
trouble, however, we canot do anything about that. In the case of kevent
or poll, this asks the context of the monitor if the file is already
there.

Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D10006
This commit is contained in:
Marcel Hollerbach 2019-09-18 11:32:08 +02:00 committed by Cedric Bail
parent 3e9f619b1d
commit 1eb24301fd
9 changed files with 88 additions and 1 deletions

View File

@ -1257,6 +1257,24 @@ EAPI const char *eio_monitor_path_get(Eio_Monitor *monitor);
* @beta
*/
EAPI Eina_Bool eio_monitor_fallback_check(const Eio_Monitor *monitor);
/**
* @brief Check if a monitor has the context about a file or not
* @param monitor The Eio_Monitor to check
* @param path The path to check
* @return EINA_TRUE if there is context, EINA_FALSE otherwise.
*
* There are Monitors that need context about a file before they can monitor the file correctly.
* As an example: If you publish a file in your API before the monitor has this file in his context,
* and the file gets deleted as a reaction to this, the monitor will not be able to emit the correct DELETE
* event even if the file is in the monitors path.
*
* In case the monitor does not yet have context, you can be sure that the monitor will bring up an FILE_ADD event about that file.
*
* @since 1.23
* @beta
*/
EAPI Eina_Bool eio_monitor_has_context(const Eio_Monitor *monitor, const char *path);
#endif
/**
* @}

View File

@ -762,6 +762,12 @@ _efl_io_model_efl_model_property_set(Eo *obj,
return efl_loop_future_rejected(obj, err);
}
static Eina_Bool
_monitor_has_context(Efl_Io_Model_Data *pd, const char *path)
{
return eio_monitor_has_context(pd->monitor, path);
}
static void
_efl_io_model_children_list(void *data, Eina_Array *entries)
{
@ -779,6 +785,7 @@ _efl_io_model_children_list(void *data, Eina_Array *entries)
{
Efl_Io_Model_Info *mi;
if (!_monitor_has_context(pd, info->path)) continue;
if (_already_added(pd, info->path)) continue;
if (pd->filter.cb)

View File

@ -411,3 +411,17 @@ eio_monitor_path_get(Eio_Monitor *monitor)
EINA_SAFETY_ON_NULL_RETURN_VAL(monitor, NULL);
return monitor->path;
}
EAPI Eina_Bool
eio_monitor_has_context(const Eio_Monitor *monitor, const char *path)
{
if (monitor->fallback)
{
return eio_monitor_fallback_context_check(monitor, path);
}
else
{
return eio_monitor_context_check(monitor, path);
}
}

View File

@ -403,6 +403,10 @@ void eio_monitor_backend_del(Eio_Monitor *monitor)
eina_hash_del(_fsevent_monitors, monitor->path, backend);
}
Eina_Bool eio_monitor_context_check(const Eio_Monitor *monitor, const char *path)
{
return EINA_TRUE;
}
/*============================================================================*
* API *

View File

@ -290,6 +290,11 @@ void eio_monitor_backend_del(Eio_Monitor *monitor)
eina_hash_del(_inotify_monitors, &backend->hwnd, backend);
}
Eina_Bool eio_monitor_context_check(const Eio_Monitor *monitor EINA_UNUSED, const char *path EINA_UNUSED)
{
return EINA_TRUE;
}
/*============================================================================*
* API *

View File

@ -299,13 +299,30 @@ error:
void eio_monitor_backend_del(Eio_Monitor *monitor)
{
Eio_Monitor_Backend *backend;
backend = monitor->backend;
monitor->backend = NULL;
eina_hash_del(_kevent_monitors, &backend->fd, backend);
}
Eina_Bool eio_monitor_context_check(const Eio_Monitor *monitor, const char *path)
{
Eio_Monitor_Backend *backend = monitor->backend;
Eina_List *l;
Eio_File_Info *file;
EINA_LIST_FOREACH(backend->prev_list, l, file)
{
if (eina_streq(file->path, path))
{
return EINA_TRUE;
}
}
return EINA_FALSE;
}
/*============================================================================*
* API *

View File

@ -315,6 +315,12 @@ void eio_monitor_backend_del(Eio_Monitor *monitor)
{
eio_monitor_fallback_del(monitor);
}
Eina_Bool eio_monitor_content_check(const Eio_Monitor *monitor, const char *path)
{
return eio_monitor_fallback_content_check(monitor, path);
}
#endif
void
@ -330,6 +336,15 @@ eio_monitor_fallback_shutdown(void)
timer_hash = NULL;
}
Eina_Bool
eio_monitor_fallback_context_check(const Eio_Monitor *monitor, const char *path)
{
Eio_Monitor_Backend *backend;
EINA_SAFETY_ON_FALSE_RETURN_VAL(monitor->fallback, EINA_TRUE);
backend = monitor->backend;
return !!eina_hash_find(backend->children, path);
}
void
eio_monitor_fallback_add(Eio_Monitor *monitor)
{

View File

@ -423,6 +423,11 @@ void eio_monitor_backend_del(Eio_Monitor *monitor)
monitor->backend = NULL;
}
Eina_Bool eio_monitor_context_check(const Eio_Monitor *monitor, const char *path)
{
return EINA_TRUE;
}
/**
* @endcond

View File

@ -486,7 +486,9 @@ void eio_monitor_shutdown(void);
void eio_monitor_backend_shutdown(void);
void eio_monitor_fallback_shutdown(void);
void eio_monitor_backend_add(Eio_Monitor *monitor);
Eina_Bool eio_monitor_context_check(const Eio_Monitor *monitor, const char *path);
void eio_monitor_fallback_add(Eio_Monitor *monitor);
Eina_Bool eio_monitor_fallback_context_check(const Eio_Monitor *monitor, const char *path);
void eio_monitor_backend_del(Eio_Monitor *monitor);
void eio_monitor_fallback_del(Eio_Monitor *monitor);