From 095ed35fc239f1a2a572c65a9e80fac65bc03c98 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Wed, 18 Sep 2019 11:32:08 +0200 Subject: [PATCH] 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 Differential Revision: https://phab.enlightenment.org/D10006 --- src/lib/eio/Eio_Legacy.h | 18 ++++++++++++++++++ src/lib/eio/efl_io_model.c | 7 +++++++ src/lib/eio/eio_monitor.c | 14 ++++++++++++++ src/lib/eio/eio_monitor_cocoa.c | 4 ++++ src/lib/eio/eio_monitor_inotify.c | 5 +++++ src/lib/eio/eio_monitor_kevent.c | 19 ++++++++++++++++++- src/lib/eio/eio_monitor_poll.c | 15 +++++++++++++++ src/lib/eio/eio_monitor_win32.c | 5 +++++ src/lib/eio/eio_private.h | 2 ++ 9 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/lib/eio/Eio_Legacy.h b/src/lib/eio/Eio_Legacy.h index 50140ed..c44340c 100644 --- a/src/lib/eio/Eio_Legacy.h +++ b/src/lib/eio/Eio_Legacy.h @@ -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 /** * @} diff --git a/src/lib/eio/efl_io_model.c b/src/lib/eio/efl_io_model.c index e6b6149..88c32b1 100644 --- a/src/lib/eio/efl_io_model.c +++ b/src/lib/eio/efl_io_model.c @@ -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) diff --git a/src/lib/eio/eio_monitor.c b/src/lib/eio/eio_monitor.c index bc1ed07..64eab21 100644 --- a/src/lib/eio/eio_monitor.c +++ b/src/lib/eio/eio_monitor.c @@ -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); + } +} diff --git a/src/lib/eio/eio_monitor_cocoa.c b/src/lib/eio/eio_monitor_cocoa.c index d491de4..be35496 100644 --- a/src/lib/eio/eio_monitor_cocoa.c +++ b/src/lib/eio/eio_monitor_cocoa.c @@ -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 * diff --git a/src/lib/eio/eio_monitor_inotify.c b/src/lib/eio/eio_monitor_inotify.c index f3a83be..e266877 100644 --- a/src/lib/eio/eio_monitor_inotify.c +++ b/src/lib/eio/eio_monitor_inotify.c @@ -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 * diff --git a/src/lib/eio/eio_monitor_kevent.c b/src/lib/eio/eio_monitor_kevent.c index 7a54f1d..b0ab7f7 100644 --- a/src/lib/eio/eio_monitor_kevent.c +++ b/src/lib/eio/eio_monitor_kevent.c @@ -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 * diff --git a/src/lib/eio/eio_monitor_poll.c b/src/lib/eio/eio_monitor_poll.c index 2a35b6f..aae582f 100644 --- a/src/lib/eio/eio_monitor_poll.c +++ b/src/lib/eio/eio_monitor_poll.c @@ -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) { diff --git a/src/lib/eio/eio_monitor_win32.c b/src/lib/eio/eio_monitor_win32.c index a2c45de..04d8534 100644 --- a/src/lib/eio/eio_monitor_win32.c +++ b/src/lib/eio/eio_monitor_win32.c @@ -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 diff --git a/src/lib/eio/eio_private.h b/src/lib/eio/eio_private.h index 9810b3b..852d431 100644 --- a/src/lib/eio/eio_private.h +++ b/src/lib/eio/eio_private.h @@ -487,7 +487,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); -- 2.7.4