forked from enlightenment/efl
Evas/cserve2: Fix crash in server on file change
An inotify callback is triggered when an image file changes, and it is supposed to cleanup all references to this image. Unfortunately, it was doing it in a very unsafe way as pointers could become invalid, because of hash free callbacks in the referenced image list. Add some list safety and always assume the pointer might be dead after free operations. TBH, this _file_changed_cb function looks very confused to me (as it tries to bypass eina_hash_del).
This commit is contained in:
parent
00417fe256
commit
6a4c84a6a4
|
@ -1673,26 +1673,27 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
|
||||||
{
|
{
|
||||||
File_Watch *fw = data;
|
File_Watch *fw = data;
|
||||||
File_Entry *fentry;
|
File_Entry *fentry;
|
||||||
Eina_List *l;
|
Eina_List *l, *l_next;
|
||||||
|
|
||||||
EINA_LIST_FOREACH(fw->entries, l, fentry)
|
EINA_LIST_FOREACH_SAFE(fw->entries, l, l_next, fentry)
|
||||||
{
|
{
|
||||||
Eina_List *ll;
|
Eina_List *ll, *ll_next;
|
||||||
Image_Entry *ie;
|
Image_Entry *ie;
|
||||||
File_Data *fd;
|
File_Data *fd;
|
||||||
|
int fentry_id = ENTRYID(fentry);
|
||||||
|
|
||||||
fentry->watcher = NULL;
|
fentry->watcher = NULL;
|
||||||
|
|
||||||
EINA_LIST_FOREACH(fentry->images, ll, ie)
|
EINA_LIST_FOREACH_SAFE(fentry->images, ll, ll_next, ie)
|
||||||
{
|
{
|
||||||
Image_Data *idata;
|
Image_Data *idata;
|
||||||
|
|
||||||
idata = _image_data_find(ENTRYID(ie));
|
idata = _image_data_find(ENTRYID(ie));
|
||||||
eina_hash_set(image_entries, &ENTRYID(ie), NULL);
|
|
||||||
if (ASENTRY(ie)->request /*&& !ie->base.request->processing*/)
|
if (ASENTRY(ie)->request /*&& !ie->base.request->processing*/)
|
||||||
cserve2_request_cancel_all(ASENTRY(ie)->request,
|
cserve2_request_cancel_all(ASENTRY(ie)->request,
|
||||||
CSERVE2_FILE_CHANGED);
|
CSERVE2_FILE_CHANGED);
|
||||||
ASENTRY(ie)->request = NULL;
|
ASENTRY(ie)->request = NULL;
|
||||||
|
eina_hash_set(image_entries, &ENTRYID(ie), NULL);
|
||||||
|
|
||||||
if (idata)
|
if (idata)
|
||||||
{
|
{
|
||||||
|
@ -1702,8 +1703,10 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from this point, fentry might have died already
|
||||||
|
// clean up if it's still alive somewhere
|
||||||
|
|
||||||
fd = _file_data_find(ENTRYID(fentry));
|
fd = _file_data_find(fentry_id);
|
||||||
if (fd)
|
if (fd)
|
||||||
{
|
{
|
||||||
fd->invalid = EINA_TRUE;
|
fd->invalid = EINA_TRUE;
|
||||||
|
@ -1711,15 +1714,19 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
|
||||||
eina_hash_set(file_entries, &fd->id, NULL);
|
eina_hash_set(file_entries, &fd->id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ASENTRY(fentry)->request
|
fentry = (File_Entry *) eina_hash_find(file_entries, &fentry_id);
|
||||||
/*&& !ASENTRY(fentry)->request->processing*/)
|
if (fentry)
|
||||||
{
|
{
|
||||||
cserve2_request_cancel_all(ASENTRY(fentry)->request,
|
if (ASENTRY(fentry)->request
|
||||||
CSERVE2_FILE_CHANGED);
|
/*&& !ASENTRY(fentry)->request->processing*/)
|
||||||
ASENTRY(fentry)->request = NULL;
|
{
|
||||||
|
cserve2_request_cancel_all(ASENTRY(fentry)->request,
|
||||||
|
CSERVE2_FILE_CHANGED);
|
||||||
|
ASENTRY(fentry)->request = NULL;
|
||||||
|
}
|
||||||
|
if (!fentry->images && !ASENTRY(fentry)->references)
|
||||||
|
_hash_file_entry_free(fentry);
|
||||||
}
|
}
|
||||||
if (!fentry->images && !ASENTRY(fentry)->references)
|
|
||||||
_hash_file_entry_free(fentry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eina_hash_del_by_key(file_watch, fw->path);
|
eina_hash_del_by_key(file_watch, fw->path);
|
||||||
|
|
Loading…
Reference in New Issue