summaryrefslogtreecommitdiff
path: root/src/bin/evas
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2014-01-13 14:21:44 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2014-01-14 14:23:04 +0900
commit6a4c84a6a48a7d02c52a1556b0ab6ded6c2de081 (patch)
tree0ad6732b45d4b5fe30b3c50c08ff007226e625bb /src/bin/evas
parent00417fe25636dc5f33b329b2f82d7d95e584e803 (diff)
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).
Diffstat (limited to 'src/bin/evas')
-rw-r--r--src/bin/evas/evas_cserve2_cache.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/src/bin/evas/evas_cserve2_cache.c b/src/bin/evas/evas_cserve2_cache.c
index bc12fed505..f4ce05ed33 100644
--- a/src/bin/evas/evas_cserve2_cache.c
+++ b/src/bin/evas/evas_cserve2_cache.c
@@ -1673,26 +1673,27 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
1673{ 1673{
1674 File_Watch *fw = data; 1674 File_Watch *fw = data;
1675 File_Entry *fentry; 1675 File_Entry *fentry;
1676 Eina_List *l; 1676 Eina_List *l, *l_next;
1677 1677
1678 EINA_LIST_FOREACH(fw->entries, l, fentry) 1678 EINA_LIST_FOREACH_SAFE(fw->entries, l, l_next, fentry)
1679 { 1679 {
1680 Eina_List *ll; 1680 Eina_List *ll, *ll_next;
1681 Image_Entry *ie; 1681 Image_Entry *ie;
1682 File_Data *fd; 1682 File_Data *fd;
1683 int fentry_id = ENTRYID(fentry);
1683 1684
1684 fentry->watcher = NULL; 1685 fentry->watcher = NULL;
1685 1686
1686 EINA_LIST_FOREACH(fentry->images, ll, ie) 1687 EINA_LIST_FOREACH_SAFE(fentry->images, ll, ll_next, ie)
1687 { 1688 {
1688 Image_Data *idata; 1689 Image_Data *idata;
1689 1690
1690 idata = _image_data_find(ENTRYID(ie)); 1691 idata = _image_data_find(ENTRYID(ie));
1691 eina_hash_set(image_entries, &ENTRYID(ie), NULL);
1692 if (ASENTRY(ie)->request /*&& !ie->base.request->processing*/) 1692 if (ASENTRY(ie)->request /*&& !ie->base.request->processing*/)
1693 cserve2_request_cancel_all(ASENTRY(ie)->request, 1693 cserve2_request_cancel_all(ASENTRY(ie)->request,
1694 CSERVE2_FILE_CHANGED); 1694 CSERVE2_FILE_CHANGED);
1695 ASENTRY(ie)->request = NULL; 1695 ASENTRY(ie)->request = NULL;
1696 eina_hash_set(image_entries, &ENTRYID(ie), NULL);
1696 1697
1697 if (idata) 1698 if (idata)
1698 { 1699 {
@@ -1702,8 +1703,10 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
1702 } 1703 }
1703 } 1704 }
1704 1705
1706 // from this point, fentry might have died already
1707 // clean up if it's still alive somewhere
1705 1708
1706 fd = _file_data_find(ENTRYID(fentry)); 1709 fd = _file_data_find(fentry_id);
1707 if (fd) 1710 if (fd)
1708 { 1711 {
1709 fd->invalid = EINA_TRUE; 1712 fd->invalid = EINA_TRUE;
@@ -1711,15 +1714,19 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
1711 eina_hash_set(file_entries, &fd->id, NULL); 1714 eina_hash_set(file_entries, &fd->id, NULL);
1712 } 1715 }
1713 1716
1714 if (ASENTRY(fentry)->request 1717 fentry = (File_Entry *) eina_hash_find(file_entries, &fentry_id);
1715 /*&& !ASENTRY(fentry)->request->processing*/) 1718 if (fentry)
1716 { 1719 {
1717 cserve2_request_cancel_all(ASENTRY(fentry)->request, 1720 if (ASENTRY(fentry)->request
1718 CSERVE2_FILE_CHANGED); 1721 /*&& !ASENTRY(fentry)->request->processing*/)
1719 ASENTRY(fentry)->request = NULL; 1722 {
1723 cserve2_request_cancel_all(ASENTRY(fentry)->request,
1724 CSERVE2_FILE_CHANGED);
1725 ASENTRY(fentry)->request = NULL;
1726 }
1727 if (!fentry->images && !ASENTRY(fentry)->references)
1728 _hash_file_entry_free(fentry);
1720 } 1729 }
1721 if (!fentry->images && !ASENTRY(fentry)->references)
1722 _hash_file_entry_free(fentry);
1723 } 1730 }
1724 1731
1725 eina_hash_del_by_key(file_watch, fw->path); 1732 eina_hash_del_by_key(file_watch, fw->path);