diff options
author | Mike Blumenkrantz <zmike@samsung.com> | 2019-08-23 13:21:58 -0400 |
---|---|---|
committer | Mike Blumenkrantz <zmike@samsung.com> | 2019-08-23 13:38:32 -0400 |
commit | 0b8605c35d89e54428b96ff04ff759208b896d7c (patch) | |
tree | fd1a781c062aef252c914af46a73af8fbb3133d6 /src/lib/eio | |
parent | 6b3d430f1262f563d940aea52cd7de613a7127c1 (diff) |
efl/io: fix race condition with child model deletion
Summary:
if an event is emitted for a child that is added to the model during a
call to _efl_io_model_children_list(), it's possible that this child
will never be detected by the model's monitor/sentry if it is deleted
before the monitor can detect it, which means there will never be a
corresponding eio event emitted
in this case, ensure that we manually remove this child from the model
since we know we've just deleted it
this fixes reliability issues with efl io model monitor unit test
@fix
Reviewers: cedric
Reviewed By: cedric
Subscribers: #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D9708
Diffstat (limited to 'src/lib/eio')
-rw-r--r-- | src/lib/eio/efl_io_model.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/src/lib/eio/efl_io_model.c b/src/lib/eio/efl_io_model.c index 824a27c..e6b6149 100644 --- a/src/lib/eio/efl_io_model.c +++ b/src/lib/eio/efl_io_model.c | |||
@@ -154,37 +154,25 @@ _efl_model_evt_added_ecore_cb(void *data, int type, void *event) | |||
154 | return EINA_TRUE; | 154 | return EINA_TRUE; |
155 | } | 155 | } |
156 | 156 | ||
157 | static Eina_Bool | 157 | static void |
158 | _efl_model_evt_deleted_ecore_cb(void *data, int type, void *event) | 158 | _model_child_remove(Efl_Io_Model_Data *pd, Eina_Stringshare *path) |
159 | { | 159 | { |
160 | Efl_Io_Model_Info *mi; | 160 | Efl_Io_Model_Info *mi; |
161 | Eina_List *l; | 161 | Eina_List *l; |
162 | Eio_Monitor_Event *ev = event; | 162 | Efl_Io_Model *obj = pd->self; |
163 | Efl_Io_Model *obj; | ||
164 | Efl_Io_Model_Data *pd = data; | ||
165 | Eina_Stringshare *spath = NULL; | ||
166 | Efl_Model_Children_Event cevt = { 0 }; | 163 | Efl_Model_Children_Event cevt = { 0 }; |
167 | unsigned int i = 0; | 164 | unsigned int i = 0; |
168 | 165 | ||
169 | if (type != EIO_MONITOR_DIRECTORY_DELETED && type != EIO_MONITOR_FILE_DELETED) | ||
170 | return EINA_TRUE; | ||
171 | |||
172 | if (ev->monitor != pd->monitor) return EINA_TRUE; | ||
173 | |||
174 | obj = pd->self; | ||
175 | |||
176 | spath = eina_stringshare_add(ev->filename); | ||
177 | |||
178 | // FIXME: Linear search is pretty slow | 166 | // FIXME: Linear search is pretty slow |
179 | EINA_LIST_FOREACH(pd->files, l, mi) | 167 | EINA_LIST_FOREACH(pd->files, l, mi) |
180 | { | 168 | { |
181 | if (mi->path == spath) | 169 | if (mi->path == path) |
182 | break ; | 170 | break ; |
183 | ++i; | 171 | ++i; |
184 | } | 172 | } |
185 | 173 | ||
186 | if (i >= eina_list_count(pd->files)) | 174 | if (i >= eina_list_count(pd->files)) |
187 | goto end; | 175 | return; |
188 | 176 | ||
189 | cevt.index = i; | 177 | cevt.index = i; |
190 | cevt.child = mi->object; | 178 | cevt.child = mi->object; |
@@ -197,8 +185,22 @@ _efl_model_evt_deleted_ecore_cb(void *data, int type, void *event) | |||
197 | 185 | ||
198 | // This will only trigger the data destruction if no object is referencing them. | 186 | // This will only trigger the data destruction if no object is referencing them. |
199 | _efl_io_model_info_free(mi, EINA_FALSE); | 187 | _efl_io_model_info_free(mi, EINA_FALSE); |
188 | } | ||
200 | 189 | ||
201 | end: | 190 | static Eina_Bool |
191 | _efl_model_evt_deleted_ecore_cb(void *data, int type, void *event) | ||
192 | { | ||
193 | Eio_Monitor_Event *ev = event; | ||
194 | Efl_Io_Model_Data *pd = data; | ||
195 | Eina_Stringshare *spath = NULL; | ||
196 | |||
197 | if (type != EIO_MONITOR_DIRECTORY_DELETED && type != EIO_MONITOR_FILE_DELETED) | ||
198 | return EINA_TRUE; | ||
199 | |||
200 | if (ev->monitor != pd->monitor) return EINA_TRUE; | ||
201 | |||
202 | spath = eina_stringshare_add(ev->filename); | ||
203 | _model_child_remove(pd, spath); | ||
202 | eina_stringshare_del(spath); | 204 | eina_stringshare_del(spath); |
203 | 205 | ||
204 | return EINA_TRUE; | 206 | return EINA_TRUE; |
@@ -221,7 +223,12 @@ static void | |||
221 | _eio_done_unlink_cb(void *data, Eio_File *handler EINA_UNUSED) | 223 | _eio_done_unlink_cb(void *data, Eio_File *handler EINA_UNUSED) |
222 | { | 224 | { |
223 | Efl_Io_Model *child = data; | 225 | Efl_Io_Model *child = data; |
226 | Efl_Io_Model_Data *child_pd, *pd; | ||
227 | |||
228 | child_pd = efl_data_scope_get(child, MY_CLASS); | ||
229 | pd = efl_data_scope_get(efl_parent_get(child), MY_CLASS); | ||
224 | 230 | ||
231 | _model_child_remove(pd, child_pd->path); | ||
225 | _eio_del_cleanup(child); | 232 | _eio_del_cleanup(child); |
226 | } | 233 | } |
227 | 234 | ||