summaryrefslogtreecommitdiff
path: root/src/lib/eo/eo.c
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2018-05-14 14:47:39 -0700
committerCedric BAIL <cedric@osg.samsung.com>2018-05-24 16:02:20 -0700
commit0bf7a5ea13b4c7670b9468150c81da6675c2a2ab (patch)
treef53fca5c149c2bd103438262d11233bc279e3f64 /src/lib/eo/eo.c
parent5c23ea00b40a0f1a51619a0525d29efdd9790c81 (diff)
eo: make sure that reporting object refcount during efl_noref, doesn't lead to recursive loop.
Diffstat (limited to 'src/lib/eo/eo.c')
-rw-r--r--src/lib/eo/eo.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 32d044e..5396a12 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -1884,8 +1884,8 @@ efl_unref(const Eo *obj_id)
1884{ 1884{
1885 EO_OBJ_POINTER_RETURN(obj_id, obj); 1885 EO_OBJ_POINTER_RETURN(obj_id, obj);
1886 1886
1887 if (EINA_UNLIKELY(obj->user_refcount == 1 && 1887 if (EINA_UNLIKELY((!obj->unref_compensate && obj->user_refcount == 1 && obj->parent) ||
1888 obj->parent)) 1888 (obj->unref_compensate && obj->user_refcount == 2 && obj->parent)))
1889 { 1889 {
1890 if (!obj->allow_parent_unref) 1890 if (!obj->allow_parent_unref)
1891 CRI("Calling efl_unref instead of efl_del or efl_parent_set(NULL). Temporary fallback in place triggered."); 1891 CRI("Calling efl_unref instead of efl_del or efl_parent_set(NULL). Temporary fallback in place triggered.");
@@ -1894,25 +1894,35 @@ efl_unref(const Eo *obj_id)
1894 return ; 1894 return ;
1895 } 1895 }
1896 1896
1897 --(obj->user_refcount); 1897 _efl_ref(obj);
1898 1898
1899 if (EINA_UNLIKELY((obj->user_refcount == 0 && !obj->parent) || 1899 if (EINA_UNLIKELY((!obj->unref_compensate) &&
1900 (obj->user_refcount == 1 && obj->parent))) 1900 ((obj->user_refcount == 1 && !obj->parent) ||
1901 (obj->user_refcount == 2 && obj->parent))))
1901 { 1902 {
1903 // We need to report efl_ref_count correctly during efl_noref, so fake it
1904 // by adjusting efl_ref_count while inside efl_unref (This should avoid
1905 // infinite loop)
1906 obj->unref_compensate = EINA_TRUE;
1907
1902 // The noref event should happen before any object in the 1908 // The noref event should happen before any object in the
1903 // tree get affected by the change in refcount. 1909 // tree get affected by the change in refcount.
1904 efl_event_callback_call((Eo *) obj_id, EFL_EVENT_NOREF, NULL); 1910 efl_event_callback_call((Eo *) obj_id, EFL_EVENT_NOREF, NULL);
1905 efl_noref((Eo *) obj_id); 1911 efl_noref((Eo *) obj_id);
1912
1913 obj->unref_compensate = EINA_FALSE;
1906 } 1914 }
1907 1915
1916 --(obj->user_refcount);
1917
1908#ifdef EO_DEBUG 1918#ifdef EO_DEBUG
1909 _eo_log_obj_ref_op(obj, EO_REF_OP_UNREF); 1919 _eo_log_obj_ref_op(obj, EO_REF_OP_UNREF);
1910#endif 1920#endif
1911 if (EINA_UNLIKELY(obj->user_refcount <= 0)) 1921 if (EINA_UNLIKELY((obj->user_refcount <= 0 && !obj->unref_compensate)))
1912 { 1922 {
1913 if (obj->user_refcount < 0) 1923 if (obj->user_refcount < 0)
1914 { 1924 {
1915 ERR("Obj:%s@%p. User refcount (%d) < 0. Too many unrefs.", 1925 CRI("Obj:%s@%p. User refcount (%d) < 0. Too many unrefs.",
1916 obj->klass->desc->name, obj_id, obj->user_refcount); 1926 obj->klass->desc->name, obj_id, obj->user_refcount);
1917 _eo_log_obj_report((Eo_Id)obj_id, EINA_LOG_LEVEL_ERR, __FUNCTION__, __FILE__, __LINE__); 1927 _eo_log_obj_report((Eo_Id)obj_id, EINA_LOG_LEVEL_ERR, __FUNCTION__, __FILE__, __LINE__);
1918 EO_OBJ_DONE(obj_id); 1928 EO_OBJ_DONE(obj_id);
@@ -1920,6 +1930,7 @@ efl_unref(const Eo *obj_id)
1920 } 1930 }
1921 _efl_unref(obj); 1931 _efl_unref(obj);
1922 } 1932 }
1933 _efl_unref(obj);
1923 EO_OBJ_DONE(obj_id); 1934 EO_OBJ_DONE(obj_id);
1924} 1935}
1925 1936
@@ -1928,7 +1939,7 @@ efl_ref_count(const Eo *obj_id)
1928{ 1939{
1929 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, 0); 1940 EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, 0);
1930 int ref; 1941 int ref;
1931 ref = obj->user_refcount; 1942 ref = obj->user_refcount - (obj->unref_compensate ? 1 : 0);
1932 EO_OBJ_DONE(obj_id); 1943 EO_OBJ_DONE(obj_id);
1933 return ref; 1944 return ref;
1934} 1945}