summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-08-11 10:24:54 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-08-11 11:23:21 +0900
commit39c791dcbc02c84fdc1ad67d8f10e1842872c111 (patch)
treefbcd78682128ea24ce8b7d3f1d9b2d42e4c1b068 /src/lib
parente2f8ba7ad9d71d7eb6638e92f9c79e9dcb8e9474 (diff)
win: Prevent crash inside ecore evas callbacks
After any complex call on the window, a foreign evas/efl callback may be triggered that could delete the window object. This leads to crashes in queued jobs or even immediately after said callback (right now EO prevents immediate memory free using eina_freeq or eina_trash so the effects aren't immediate). Funnily enough, this was a known issue according to some comments, but no one bothered fixing it... In this particular instance, a focus_out job was crashing while trying to access now-invalid sd data. I believe some uses of ELM_WIN_DATA_GET() may still be slightly unsafe but most look like they should be the result of an EO call on the object (eg. a call to efl_event_callback_call), which ensures the object is alive. Fixes T5869
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/elementary/efl_ui_win.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c
index f7f394b9c1..3643a3d6a6 100644
--- a/src/lib/elementary/efl_ui_win.c
+++ b/src/lib/elementary/efl_ui_win.c
@@ -59,6 +59,14 @@ static const Elm_Win_Trap *trap = NULL;
59 return __VA_ARGS__; \ 59 return __VA_ARGS__; \
60 } 60 }
61 61
62// Ecore_Evas callbacks are unsafe unlike EO calls. As a consequence a user
63// callback (eg evas cb, efl event cb, ...) could be triggered that deletes the
64// object. This macro ensures the sd data is still valid after a foreign call.
65#define ELM_WIN_DATA_ALIVE_CHECK(_obj, _sd, ...) do { \
66 _sd = efl_data_scope_safe_get(_obj, MY_CLASS); \
67 if (EINA_UNLIKELY(!(_sd))) { return __VA_ARGS__; } \
68 } while (0)
69
62#define ENGINE_GET() (_elm_preferred_engine ? _elm_preferred_engine : _elm_config->engine) 70#define ENGINE_GET() (_elm_preferred_engine ? _elm_preferred_engine : _elm_config->engine)
63 71
64typedef struct _Efl_Ui_Win_Data Efl_Ui_Win_Data; 72typedef struct _Efl_Ui_Win_Data Efl_Ui_Win_Data;
@@ -800,9 +808,7 @@ static Efl_Ui_Win_Data *
800_elm_win_associate_get(const Ecore_Evas *ee) 808_elm_win_associate_get(const Ecore_Evas *ee)
801{ 809{
802 Evas_Object *obj = ecore_evas_data_get(ee, "elm_win"); 810 Evas_Object *obj = ecore_evas_data_get(ee, "elm_win");
803 if (!obj) return NULL; 811 return efl_data_scope_safe_get(obj, MY_CLASS);
804 ELM_WIN_DATA_GET(obj, sd);
805 return sd;
806} 812}
807 813
808/* Interceptors Callbacks */ 814/* Interceptors Callbacks */
@@ -871,17 +877,21 @@ _elm_win_move(Ecore_Evas *ee)
871{ 877{
872 Efl_Ui_Win_Data *sd = _elm_win_associate_get(ee); 878 Efl_Ui_Win_Data *sd = _elm_win_associate_get(ee);
873 int x, y; 879 int x, y;
880 Eo *obj;
874 881
875 if (!sd) return; 882 if (!sd) return;
883 obj = sd->obj;
876 884
877 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL); 885 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
878 sd->screen.x = x; 886 sd->screen.x = x;
879 sd->screen.y = y; 887 sd->screen.y = y;
880 efl_event_callback_legacy_call(sd->obj, EFL_GFX_EVENT_MOVE, NULL); 888 efl_event_callback_legacy_call(sd->obj, EFL_GFX_EVENT_MOVE, NULL);
889 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
881 evas_nochange_push(evas_object_evas_get(sd->obj)); 890 evas_nochange_push(evas_object_evas_get(sd->obj));
882 sd->response++; 891 sd->response++;
883 sd->req_xy = EINA_FALSE; 892 sd->req_xy = EINA_FALSE;
884 evas_object_move(sd->obj, x, y); 893 evas_object_move(sd->obj, x, y);
894 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
885 sd->response--; 895 sd->response--;
886 evas_nochange_pop(evas_object_evas_get(sd->obj)); 896 evas_nochange_pop(evas_object_evas_get(sd->obj));
887} 897}
@@ -932,13 +942,17 @@ static void
932_elm_win_pre_render(Ecore_Evas *ee) 942_elm_win_pre_render(Ecore_Evas *ee)
933{ 943{
934 Efl_Ui_Win_Data *sd = _elm_win_associate_get(ee); 944 Efl_Ui_Win_Data *sd = _elm_win_associate_get(ee);
945 Eo *obj;
946
935 if (!sd) return; 947 if (!sd) return;
948 obj = sd->obj;
936 949
937 _elm_win_throttle_ok = EINA_TRUE; 950 _elm_win_throttle_ok = EINA_TRUE;
938 if (!sd->first_draw) 951 if (!sd->first_draw)
939 { 952 {
940 sd->first_draw = EINA_TRUE; 953 sd->first_draw = EINA_TRUE;
941 _elm_win_frame_obj_update(sd); 954 _elm_win_frame_obj_update(sd);
955 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
942 } 956 }
943 if (sd->deferred_resize_job) 957 if (sd->deferred_resize_job)
944 _elm_win_resize_job(sd->obj); 958 _elm_win_resize_job(sd->obj);
@@ -967,6 +981,7 @@ _elm_win_mouse_in(Ecore_Evas *ee)
967 sd->pointer.visible = EINA_TRUE; 981 sd->pointer.visible = EINA_TRUE;
968 sd->pointer.surf = ecore_wl2_window_surface_get(sd->pointer.win); 982 sd->pointer.surf = ecore_wl2_window_surface_get(sd->pointer.win);
969 _elm_win_wl_cursor_set(sd->obj, NULL); 983 _elm_win_wl_cursor_set(sd->obj, NULL);
984 //ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
970 ecore_evas_show(sd->pointer.ee); 985 ecore_evas_show(sd->pointer.ee);
971 } 986 }
972#endif 987#endif
@@ -1207,6 +1222,7 @@ _elm_win_focus_in(Ecore_Evas *ee)
1207 obj = sd->obj; 1222 obj = sd->obj;
1208 1223
1209 _elm_widget_top_win_focused_set(obj, EINA_TRUE); 1224 _elm_widget_top_win_focused_set(obj, EINA_TRUE);
1225 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1210 if (sd->type != ELM_WIN_FAKE) 1226 if (sd->type != ELM_WIN_FAKE)
1211 { 1227 {
1212 if (!elm_widget_focus_order_get(obj)) 1228 if (!elm_widget_focus_order_get(obj))
@@ -1227,9 +1243,9 @@ _elm_win_focus_in(Ecore_Evas *ee)
1227 evas_object_focus_set(obj, EINA_TRUE); 1243 evas_object_focus_set(obj, EINA_TRUE);
1228 } 1244 }
1229 } 1245 }
1230 // FIXME: the event is deprecated but still in use. 1246
1231 // Has to be removed in EFL2.0
1232 evas_object_smart_callback_call(obj, SIG_FOCUS_IN, NULL); 1247 evas_object_smart_callback_call(obj, SIG_FOCUS_IN, NULL);
1248 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1233 sd->focus_highlight.cur.visible = EINA_TRUE; 1249 sd->focus_highlight.cur.visible = EINA_TRUE;
1234 _elm_win_focus_highlight_reconfigure_job_start(sd); 1250 _elm_win_focus_highlight_reconfigure_job_start(sd);
1235 _elm_win_frame_style_update(sd, 0, 1); 1251 _elm_win_frame_style_update(sd, 0, 1);
@@ -1257,9 +1273,9 @@ _elm_win_focus_out(Ecore_Evas *ee)
1257 obj = sd->obj; 1273 obj = sd->obj;
1258 1274
1259 _elm_widget_top_win_focused_set(obj, EINA_FALSE); 1275 _elm_widget_top_win_focused_set(obj, EINA_FALSE);
1260 // FIXME: the event is deprecated but still in use. 1276 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1261 // Has to be removed in EFL2.0
1262 evas_object_smart_callback_call(obj, SIG_FOCUS_OUT, NULL); 1277 evas_object_smart_callback_call(obj, SIG_FOCUS_OUT, NULL);
1278 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1263 sd->focus_highlight.cur.visible = EINA_FALSE; 1279 sd->focus_highlight.cur.visible = EINA_FALSE;
1264 _elm_win_focus_highlight_reconfigure_job_start(sd); 1280 _elm_win_focus_highlight_reconfigure_job_start(sd);
1265 if (!sd->resizing) 1281 if (!sd->resizing)
@@ -1523,6 +1539,7 @@ _elm_win_state_change(Ecore_Evas *ee)
1523 ch_profile = _internal_elm_win_profile_set(sd, profile); 1539 ch_profile = _internal_elm_win_profile_set(sd, profile);
1524 } 1540 }
1525 1541
1542 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1526 if (sd->wm_rot.use) 1543 if (sd->wm_rot.use)
1527 { 1544 {
1528 if (sd->rot != ecore_evas_rotation_get(sd->ee)) 1545 if (sd->rot != ecore_evas_rotation_get(sd->ee))
@@ -1536,6 +1553,7 @@ _elm_win_state_change(Ecore_Evas *ee)
1536 1553
1537 if ((ch_withdrawn) || (ch_iconified)) 1554 if ((ch_withdrawn) || (ch_iconified))
1538 { 1555 {
1556 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1539 if (sd->withdrawn) 1557 if (sd->withdrawn)
1540 efl_event_callback_legacy_call(obj, EFL_UI_WIN_EVENT_WITHDRAWN, NULL); 1558 efl_event_callback_legacy_call(obj, EFL_UI_WIN_EVENT_WITHDRAWN, NULL);
1541 else if (sd->iconified) 1559 else if (sd->iconified)
@@ -1567,6 +1585,7 @@ _elm_win_state_change(Ecore_Evas *ee)
1567#endif 1585#endif
1568 if (ch_fullscreen) 1586 if (ch_fullscreen)
1569 { 1587 {
1588 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1570 _elm_win_frame_style_update(sd, 0, 1); 1589 _elm_win_frame_style_update(sd, 0, 1);
1571 if (sd->fullscreen) 1590 if (sd->fullscreen)
1572 { 1591 {
@@ -1582,6 +1601,7 @@ _elm_win_state_change(Ecore_Evas *ee)
1582 } 1601 }
1583 if (ch_maximized) 1602 if (ch_maximized)
1584 { 1603 {
1604 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1585 _elm_win_frame_style_update(sd, 0, 1); 1605 _elm_win_frame_style_update(sd, 0, 1);
1586 if (sd->maximized) 1606 if (sd->maximized)
1587 { 1607 {
@@ -1598,6 +1618,7 @@ _elm_win_state_change(Ecore_Evas *ee)
1598 } 1618 }
1599 if (ch_profile) 1619 if (ch_profile)
1600 { 1620 {
1621 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1601 _elm_win_profile_update(sd); 1622 _elm_win_profile_update(sd);
1602 } 1623 }
1603 if (ch_wm_rotation) 1624 if (ch_wm_rotation)
@@ -1605,8 +1626,10 @@ _elm_win_state_change(Ecore_Evas *ee)
1605 efl_gfx_size_hint_restricted_min_set(obj, -1, -1); 1626 efl_gfx_size_hint_restricted_min_set(obj, -1, -1);
1606 efl_gfx_size_hint_max_set(obj, -1, -1); 1627 efl_gfx_size_hint_max_set(obj, -1, -1);
1607#ifdef HAVE_ELEMENTARY_X 1628#ifdef HAVE_ELEMENTARY_X
1629 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1608 _elm_win_xwin_update(sd); 1630 _elm_win_xwin_update(sd);
1609#endif 1631#endif
1632 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
1610 elm_widget_orientation_set(obj, sd->rot); 1633 elm_widget_orientation_set(obj, sd->rot);
1611 efl_event_callback_legacy_call 1634 efl_event_callback_legacy_call
1612 (obj, EFL_UI_WIN_EVENT_ROTATION_CHANGED, NULL); 1635 (obj, EFL_UI_WIN_EVENT_ROTATION_CHANGED, NULL);
@@ -3026,11 +3049,13 @@ _elm_win_delete_request(Ecore_Evas *ee)
3026 sd->autodel_clear = &autodel; 3049 sd->autodel_clear = &autodel;
3027 evas_object_ref(obj); 3050 evas_object_ref(obj);
3028 efl_event_callback_legacy_call(obj, EFL_UI_WIN_EVENT_DELETE_REQUEST, NULL); 3051 efl_event_callback_legacy_call(obj, EFL_UI_WIN_EVENT_DELETE_REQUEST, NULL);
3052 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
3029 if (sd->autohide) 3053 if (sd->autohide)
3030 evas_object_hide(obj); 3054 evas_object_hide(obj);
3031 // FIXME: if above callback deletes - then the below will be invalid 3055 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
3032 if (_elm_config->atspi_mode) 3056 if (_elm_config->atspi_mode)
3033 elm_interface_atspi_window_destroyed_signal_emit(obj); 3057 elm_interface_atspi_window_destroyed_signal_emit(obj);
3058 ELM_WIN_DATA_ALIVE_CHECK(obj, sd);
3034 if (autodel) evas_object_del(obj); 3059 if (autodel) evas_object_del(obj);
3035 else sd->autodel_clear = NULL; 3060 else sd->autodel_clear = NULL;
3036 evas_object_unref(obj); 3061 evas_object_unref(obj);