From 6b64e40122004f5e45f387e8d85781110323d2fb Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Mon, 15 Jun 2015 20:27:25 +0900 Subject: [PATCH] e - e client, comp win etc. reffing fix ... part 2 this follows 56cabf59c672af27af87eda82079de4e2ee2d38e then 4e5521b4d82063a2fbf6632a117fda201cc1687d where i have been trying to fix a crash with e client and comp win references etc. i have gone over all referencing with a fine tooth comb and found all the nigglies i can., no leaks now, no crashes, no valgrind complaints etc. so i call this fixed now. as best i know this is new in e20, so not a backport fix --- src/bin/e.h | 27 ++++++++ src/bin/e_client.c | 13 +++- src/bin/e_comp.c | 6 +- src/bin/e_comp_canvas.c | 1 + src/bin/e_comp_object.c | 134 +++++++++++++++++++--------------------- src/bin/e_comp_x.c | 12 +++- src/bin/e_exec.c | 9 +-- src/bin/e_remember.c | 2 + 8 files changed, 125 insertions(+), 79 deletions(-) diff --git a/src/bin/e.h b/src/bin/e.h index d8afcefa1..d3fd4095f 100644 --- a/src/bin/e.h +++ b/src/bin/e.h @@ -341,4 +341,31 @@ extern EINTERN double e_first_frame_start_time; * @} */ +#if 0 +#define REFD(obj, num) \ + do { \ + printf("%p <- %5i <- ref | %s-%i\n", \ + obj, E_OBJECT(obj)->references, \ + __FILE__, num); \ + } while (0) + +#define UNREFD(obj, num) \ + do { \ + printf("%p <- %5i <- unref | %s-%i\n", \ + obj, E_OBJECT(obj)->references, \ + __FILE__, num); \ + } while (0) + +#define DELD(obj, num) \ + do { \ + printf("%p <- %5i <- del | %s-%i\n", \ + obj, E_OBJECT(obj)->references, \ + __FILE__, num); \ + } while (0) +#else +# define REFD(obj, num) +# define UNREFD(obj, num) +# define DELD(obj, num) +#endif + #endif diff --git a/src/bin/e_client.c b/src/bin/e_client.c index 7f01963c4..e600e3927 100644 --- a/src/bin/e_client.c +++ b/src/bin/e_client.c @@ -175,6 +175,7 @@ _e_client_cb_drag_finished(E_Drag *drag, int dropped EINA_UNUSED) E_Client *ec; ec = drag->data; + UNREFD(ec, 1); e_object_unref(E_OBJECT(ec)); client_drag = NULL; } @@ -328,6 +329,7 @@ _e_client_hook_call(E_Client_Hook_Point hookpoint, E_Client *ec) static void _e_client_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev) { + UNREFD(ev->ec, 3); e_object_unref(E_OBJECT(ev->ec)); free(ev); } @@ -339,6 +341,7 @@ _e_client_event_simple(E_Client *ec, int type) ev = E_NEW(E_Event_Client, 1); ev->ec = ec; + REFD(ec, 3); e_object_ref(E_OBJECT(ec)); ecore_event_add(type, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL); } @@ -351,6 +354,7 @@ _e_client_event_property(E_Client *ec, int prop) ev = E_NEW(E_Event_Client_Property, 1); ev->ec = ec; ev->property = prop; + REFD(ec, 33); e_object_ref(E_OBJECT(ec)); ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL); } @@ -358,6 +362,7 @@ _e_client_event_property(E_Client *ec, int prop) static void _e_client_event_desk_set_free(void *d EINA_UNUSED, E_Event_Client_Desk_Set *ev) { + UNREFD(ev->ec, 4); e_object_unref(E_OBJECT(ev->ec)); e_object_unref(E_OBJECT(ev->desk)); free(ev); @@ -366,6 +371,7 @@ _e_client_event_desk_set_free(void *d EINA_UNUSED, E_Event_Client_Desk_Set *ev) static void _e_client_event_zone_set_free(void *d EINA_UNUSED, E_Event_Client_Zone_Set *ev) { + UNREFD(ev->ec, 5); e_object_unref(E_OBJECT(ev->ec)); e_object_unref(E_OBJECT(ev->zone)); free(ev); @@ -439,6 +445,7 @@ _e_client_free(E_Client *ec) e_comp_object_redirected_set(ec->frame, 0); e_comp_object_render_update_del(ec->frame); + E_OBJECT(ec)->references++; if (ec->fullscreen) { ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec); @@ -531,7 +538,6 @@ _e_client_free(E_Client *ec) raise_stack = eina_list_remove(raise_stack, ec); e_hints_client_list_set(); - evas_object_del(ec->frame); if (ec->e.state.profile.wait_desk) { e_object_delfn_del(E_OBJECT(ec->e.state.profile.wait_desk), @@ -540,6 +546,8 @@ _e_client_free(E_Client *ec) e_object_unref(E_OBJECT(ec->e.state.profile.wait_desk)); } ec->e.state.profile.wait_desk = NULL; + evas_object_del(ec->frame); + E_OBJECT(ec)->references--; free(ec); } @@ -2664,6 +2672,7 @@ e_client_desk_set(E_Client *ec, E_Desk *desk) { ev = E_NEW(E_Event_Client_Desk_Set, 1); ev->ec = ec; + UNREFD(ec, 4); e_object_ref(E_OBJECT(ec)); ev->desk = old_desk; e_object_ref(E_OBJECT(old_desk)); @@ -2949,6 +2958,7 @@ e_client_mouse_move(E_Client *ec, Evas_Point *output) int x, y, w, h; const char *drag_types[] = { "enlightenment/border" }; + REFD(ec, 1); e_object_ref(E_OBJECT(ec)); e_comp_object_frame_icon_geometry_get(ec->frame, &x, &y, &w, &h); @@ -3119,6 +3129,7 @@ e_client_zone_set(E_Client *ec, E_Zone *zone) ev = E_NEW(E_Event_Client_Zone_Set, 1); ev->ec = ec; + REFD(ec, 5); e_object_ref(E_OBJECT(ec)); ev->zone = zone; e_object_ref(E_OBJECT(zone)); diff --git a/src/bin/e_comp.c b/src/bin/e_comp.c index 2b8e482b9..8290fb6c8 100644 --- a/src/bin/e_comp.c +++ b/src/bin/e_comp.c @@ -374,6 +374,7 @@ _e_comp_cb_update(void) if (_e_comp_client_update(ec)) { e_comp->post_updates = eina_list_append(e_comp->post_updates, ec); + REFD(ec, 111); e_object_ref(E_OBJECT(ec)); } } @@ -1294,7 +1295,10 @@ e_comp_shutdown(void) #endif E_FREE_FUNC(action_timeout, ecore_timer_del); while (e_comp->clients) - e_object_del(eina_list_data_get(e_comp->clients)); + { + DELD(eina_list_data_get(e_comp->clients), 99999); + e_object_del(eina_list_data_get(e_comp->clients)); + } e_object_del(E_OBJECT(e_comp)); E_FREE_LIST(handlers, ecore_event_handler_del); E_FREE_LIST(actions, e_object_del); diff --git a/src/bin/e_comp_canvas.c b/src/bin/e_comp_canvas.c index 736993b56..70f610115 100644 --- a/src/bin/e_comp_canvas.c +++ b/src/bin/e_comp_canvas.c @@ -53,6 +53,7 @@ _e_comp_canvas_render_post(void *data EINA_UNUSED, Evas *e EINA_UNUSED, void *ev //INF("POST %p", ec); if (!e_object_is_del(E_OBJECT(ec))) e_pixmap_image_clear(ec->pixmap, 1); + UNREFD(ec, 111); e_object_unref(E_OBJECT(ec)); } } diff --git a/src/bin/e_comp_object.c b/src/bin/e_comp_object.c index 665952e98..31dc7f689 100644 --- a/src/bin/e_comp_object.c +++ b/src/bin/e_comp_object.c @@ -147,7 +147,11 @@ _e_comp_object_event_free(void *d EINA_UNUSED, void *event) E_Client *ec; ec = evas_object_data_get(ev->comp_object, "E_Client"); - if (ec) e_object_unref(E_OBJECT(ec)); + if (ec) + { + UNREFD(ec, 1); + e_object_unref(E_OBJECT(ec)); + } evas_object_unref(ev->comp_object); free(ev); } @@ -163,7 +167,11 @@ _e_comp_object_event_add(Evas_Object *obj) evas_object_ref(obj); ev->comp_object = obj; ec = evas_object_data_get(ev->comp_object, "E_Client"); - if (ec) e_object_ref(E_OBJECT(ec)); + if (ec) + { + REFD(ec, 1); + e_object_ref(E_OBJECT(ec)); + } ecore_event_add(E_EVENT_COMP_OBJECT_ADD, ev, _e_comp_object_event_free, NULL); } @@ -647,6 +655,35 @@ _e_comp_object_shadow_setup(E_Comp_Object *cw) ///////////////////////////////////////////// +static void +_e_comp_object_animating_begin(E_Comp_Object *cw) +{ + cw->animating++; + if (cw->animating == 1) + { + e_comp->animating++; + REFD(cw->ec, 2); + e_object_ref(E_OBJECT(cw->ec)); + } +} + +static Eina_Bool +_e_comp_object_animating_end(E_Comp_Object *cw) +{ + if (cw->animating) + { + cw->animating--; + if (!cw->animating) + { + e_comp->animating--; + UNREFD(cw->ec, 2); + /* remove ref from animation start, account for possibility of deletion from unref */ + return e_object_unref(E_OBJECT(cw->ec)); + } + } + return EINA_TRUE; +} + /* handle the end of a compositor animation */ static void _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED) @@ -657,16 +694,7 @@ _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char * /* visible clients which have never been sized are a bug */ if ((!cw->ec->new_client) && (!cw->ec->changes.size) && ((cw->w < 0) || (cw->h < 0)) && (!strcmp(emission, "e,action,show,done"))) CRI("ACK!"); - if (cw->animating) - { - cw->animating--; - if (!cw->animating) - { - e_comp->animating--; - /* remove ref from animation start, account for possibility of deletion from unref */ - if (!e_object_unref(E_OBJECT(cw->ec))) return; - } - } + if (!_e_comp_object_animating_end(cw)) return; if (cw->animating) return; /* hide only after animation finishes to guarantee a full run of the animation */ if (cw->defer_hide && ((!strcmp(emission, "e,action,hide,done")) || (!strcmp(emission, "e,action,done")))) @@ -1298,21 +1326,10 @@ _e_comp_intercept_hide(void *data, Evas_Object *obj) else { e_comp_object_signal_emit(obj, "e,state,hidden", "e"); - cw->animating++; - if (cw->animating == 1) - { - e_comp->animating++; - e_object_ref(E_OBJECT(cw->ec)); - } + _e_comp_object_animating_begin(cw); if (cw->visibility_effect) { - cw->animating++; -// same as above, but unreachable -// if (cw->animating == 1) -// { -// e_comp->animating++; -// e_object_ref(E_OBJECT(cw->ec)); -// } + _e_comp_object_animating_begin(cw); e_comp_object_effect_set(obj, cw->visibility_effect); e_comp_object_effect_params_set(obj, 0, (int[]){0}, 1); e_comp_object_effect_start(obj, _e_comp_object_done_defer, cw); @@ -2049,21 +2066,10 @@ _e_comp_smart_show(Evas_Object *obj) else { e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e"); - cw->animating++; - if (cw->animating == 1) - { - e_comp->animating++; - e_object_ref(E_OBJECT(cw->ec)); - } + _e_comp_object_animating_begin(cw); if (cw->visibility_effect) { - cw->animating++; -// same logic as above but unreachable -// if (cw->animating == 1) -// { -// e_comp->animating++; -// e_object_ref(E_OBJECT(cw->ec)); -// } + _e_comp_object_animating_begin(cw); e_comp_object_effect_set(obj, cw->visibility_effect); e_comp_object_effect_params_set(obj, 0, (int[]){1}, 1); e_comp_object_effect_start(obj, _e_comp_object_done_defer, cw); @@ -2084,16 +2090,9 @@ _e_comp_smart_del(Evas_Object *obj) INTERNAL_ENTRY; - if (cw->animating) - { - e_comp->animating--; - e_object_unref(E_OBJECT(cw->ec)); - } - cw->animating = 0; + e_comp_object_render_update_del(cw->smart_obj); E_FREE_FUNC(cw->updates, eina_tiler_free); E_FREE_FUNC(cw->pending_updates, eina_tiler_free); - DBG(" [%p] del", cw->ec); - e_comp_object_render_update_del(cw->smart_obj); if (cw->obj_mirror) { @@ -2121,6 +2120,15 @@ _e_comp_smart_del(Evas_Object *obj) e_comp_shape_queue(); eina_stringshare_del(cw->frame_theme); eina_stringshare_del(cw->frame_name); + if (cw->animating) + { + cw->animating = 0; + e_comp->animating--; + UNREFD(cw->ec, 2); + e_object_unref(E_OBJECT(cw->ec)); + } +// UNREFD(cw->ec, 9); +// e_object_unref(E_OBJECT(cw->ec)); free(cw); } @@ -2542,6 +2550,8 @@ e_comp_object_client_add(E_Client *ec) o = evas_object_smart_add(e_comp->evas, _e_comp_smart); cw = evas_object_smart_data_get(o); evas_object_data_set(o, "E_Client", ec); +// REFD(ec, 9); +// e_object_ref(E_OBJECT(ec)); cw->ec = ec; ec->frame = o; evas_object_data_set(o, "comp_object", (void*)1); @@ -3411,6 +3421,7 @@ e_comp_object_render(Evas_Object *obj) e_comp_object_damage(obj, 0, 0, pw, ph); else { + DELD(cw->ec, 2); e_object_del(E_OBJECT(cw->ec)); return EINA_FALSE; } @@ -3444,6 +3455,7 @@ e_comp_object_render(Evas_Object *obj) e_comp_object_damage(obj, 0, 0, pw, ph); else { + DELD(cw->ec, 3); e_object_del(E_OBJECT(cw->ec)); return EINA_FALSE; } @@ -3591,16 +3603,8 @@ _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, E_Comp_Object *cw = data; edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL); - if (cw->animating) - { - cw->animating--; - if (!cw->animating) - { - e_comp->animating--; - if (e_object_unref(E_OBJECT(cw->ec))) e_comp_shape_queue(); - } - } - + if (!_e_comp_object_animating_end(cw)) return; + e_comp_shape_queue(); end_cb = evas_object_data_get(obj, "_e_comp.end_cb"); if (!end_cb) return; end_data = evas_object_data_get(obj, "_e_comp.end_data"); @@ -3645,13 +3649,7 @@ e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void * edje_object_signal_emit(cw->effect_obj, "e,action,go", "e"); if (cw->animating) return; - cw->animating++; -// same standard logic but useless here -// if (cw->animating == 1) -// { - e_comp->animating++; - e_object_ref(E_OBJECT(cw->ec)); -// } + _e_comp_object_animating_begin(cw); } /* stop a currently-running effect immediately */ @@ -3668,15 +3666,7 @@ e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb) } edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e"); edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw); - if (cw->animating) - { - cw->animating--; - if (!cw->animating) - { - e_comp->animating--; - e_object_unref(E_OBJECT(cw->ec)); - } - } + _e_comp_object_animating_end(cw); } static int diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index 6f77a0b17..a6f2d36f5 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -101,6 +101,7 @@ _e_comp_x_client_event_free(void *d EINA_UNUSED, void *e) { E_Event_Client *ev = e; + UNREFD(ev->ec, 1); e_object_unref(E_OBJECT(ev->ec)); free(ev); } @@ -166,12 +167,14 @@ _e_comp_x_client_new_helper(E_Client *ec) if (!ecore_x_window_attributes_get(win, &ec->comp_data->initial_attributes)) { //CRI("OUCH! FIX THIS!"); + DELD(ec, 1); e_object_del(E_OBJECT(ec)); return EINA_FALSE; } if (ec->re_manage && (!ec->comp_data->initial_attributes.visible)) { /* ain't gonna be no hidden clients on my watch! */ + DELD(ec, 1); e_object_del(E_OBJECT(ec)); return EINA_FALSE; } @@ -188,6 +191,7 @@ _e_comp_x_client_new_helper(E_Client *ec) { /* this is the ecore-x private window :/ */ e_comp_ignore_win_add(E_PIXMAP_TYPE_X, win); + DELD(ec, 1); e_object_del(E_OBJECT(ec)); return EINA_FALSE; } @@ -1032,6 +1036,7 @@ _e_comp_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Wi evas_object_pass_events_set(ec->frame, 1); evas_object_hide(ec->frame); ec->comp_data->deleted = 1; + DELD(ec, 2); e_object_del(E_OBJECT(ec)); } return ECORE_CALLBACK_PASS_ON; @@ -1294,6 +1299,7 @@ _e_comp_x_hide(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Windo { if (ec->exe_inst && ec->exe_inst->exe) ec->exe_inst->phony = 0; + DELD(ec, 3); e_object_del(E_OBJECT(ec)); } } @@ -3040,6 +3046,7 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec) ev = E_NEW(E_Event_Client_Property, 1); ev->ec = ec; + REFD(ec, 1); e_object_ref(E_OBJECT(ec)); ev->property = E_CLIENT_PROPERTY_NETWM_STATE; ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, _e_comp_x_client_event_free, NULL); @@ -4722,7 +4729,10 @@ _e_comp_x_manage_windows(void) ec = _e_comp_x_client_new(windows[i], 1); } if (ec && (!ec->comp_data->initial_attributes.visible)) - E_FREE_FUNC(ec, e_object_del); + { + DELD(ec, 3); + E_FREE_FUNC(ec, e_object_del); + } if (ec) { if (ec->override) diff --git a/src/bin/e_exec.c b/src/bin/e_exec.c index d538a0feb..c6c78f2d4 100644 --- a/src/bin/e_exec.c +++ b/src/bin/e_exec.c @@ -359,8 +359,9 @@ e_exec_instance_found(E_Exec_Instance *inst) E_API void e_exec_instance_client_add(E_Exec_Instance *inst, E_Client *ec) { - e_object_ref(E_OBJECT(ec)); inst->clients = eina_list_append(inst->clients, ec); + REFD(ec, 2); + e_object_ref(E_OBJECT(ec)); ec->exe_inst = inst; inst->ref++; ecore_event_add(E_EVENT_EXEC_NEW_CLIENT, inst, _e_exec_cb_exec_new_client_free, ec); @@ -660,7 +661,6 @@ _e_exec_instance_free(E_Exec_Instance *inst) if (!inst->deleted) { inst->deleted = 1; - E_LIST_FOREACH(inst->clients, e_object_ref); ecore_event_add(E_EVENT_EXEC_DEL, inst, _e_exec_cb_exec_del_free, inst); return; } @@ -671,7 +671,6 @@ _e_exec_instance_free(E_Exec_Instance *inst) EINA_LIST_FREE(inst->clients, ec) { ec->exe_inst = NULL; - e_object_unref(E_OBJECT(ec)); } if (inst->desktop) efreet_desktop_free(inst->desktop); if (!inst->phony) @@ -694,10 +693,12 @@ static void _e_exec_cb_exec_new_client_free(void *data, void *ev) { E_Exec_Instance *inst = ev; + E_Client *ec = data; inst->ref--; _e_exec_instance_free(inst); - e_object_unref(data); + UNREFD(ec, 1); + e_object_unref(E_OBJECT(ec)); } static void diff --git a/src/bin/e_remember.c b/src/bin/e_remember.c index 4651703d6..cf9d63cae 100644 --- a/src/bin/e_remember.c +++ b/src/bin/e_remember.c @@ -387,6 +387,7 @@ static void _e_remember_event_free(void *d EINA_UNUSED, void *event) { E_Event_Remember_Update *ev = event; + printf("unref10: %p\n", ev->ec); e_object_unref(E_OBJECT(ev->ec)); free(ev); } @@ -493,6 +494,7 @@ _e_remember_update(E_Client *ec, E_Remember *rem) ev = malloc(sizeof(E_Event_Remember_Update)); if (!ev) return; ev->ec = ec; + printf("ref10: %p\n", ec); e_object_ref(E_OBJECT(ec)); ecore_event_add(E_EVENT_REMEMBER_UPDATE, ev, _e_remember_event_free, NULL); }