summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2015-01-26 15:49:16 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-04-14 01:06:57 -0300
commit5043dcb830e96aa11b04e3bebc935c1c4cc606f2 (patch)
tree169b8e4dbf17c1d249d50bdbf222cd322fe2c7a9
parent3b441cdf4a83383f4cd55ca8569e8eb98d45868e (diff)
eo_cxx: Fix signal_connection disconnect crash
Fixed crash when disconnecting event inside of its own event callback. Instead of deleting the callback object immediately during disconnection (which causes the callback to be freed), the deletion is now scheduled for later (using ecore_main_loop_thread_safe_call_async). Updated some Makefiles to proper include ecore now that it is used in all event wrappers. Added a unit test to verify crashes under these circumstances.
-rw-r--r--src/Makefile_Eina_Cxx.am1
-rw-r--r--src/Makefile_Eolian_Cxx.am2
-rw-r--r--src/bindings/eo_cxx/eo_event.hh9
-rw-r--r--src/tests/eolian_cxx/eolian_cxx_test_callback.cc54
4 files changed, 64 insertions, 2 deletions
diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am
index 4607ece..70ef18a 100644
--- a/src/Makefile_Eina_Cxx.am
+++ b/src/Makefile_Eina_Cxx.am
@@ -64,6 +64,7 @@ tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
64-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_cxx\" \ 64-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_cxx\" \
65@CHECK_CFLAGS@ \ 65@CHECK_CFLAGS@ \
66@EO_CFLAGS@ \ 66@EO_CFLAGS@ \
67@ECORE_CFLAGS@ \
67@EO_CXX_CFLAGS@ \ 68@EO_CXX_CFLAGS@ \
68@EINA_CXX_CFLAGS@ 69@EINA_CXX_CFLAGS@
69tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@ 70tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am
index 6dff267..d086bff 100644
--- a/src/Makefile_Eolian_Cxx.am
+++ b/src/Makefile_Eolian_Cxx.am
@@ -118,7 +118,7 @@ tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
118tests_eolian_cxx_eolian_cxx_suite_CFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS} 118tests_eolian_cxx_eolian_cxx_suite_CFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
119tests_eolian_cxx_eolian_cxx_suite_CPPFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS} 119tests_eolian_cxx_eolian_cxx_suite_CPPFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
120tests_eolian_cxx_eolian_cxx_suite_LDADD = \ 120tests_eolian_cxx_eolian_cxx_suite_LDADD = \
121@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@ 121@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_ECORE_LIBS@ @USE_EOLIAN_LIBS@
122tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@ 122tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
123 123
124endif 124endif
diff --git a/src/bindings/eo_cxx/eo_event.hh b/src/bindings/eo_cxx/eo_event.hh
index f3d2e51..44c66af 100644
--- a/src/bindings/eo_cxx/eo_event.hh
+++ b/src/bindings/eo_cxx/eo_event.hh
@@ -7,6 +7,7 @@
7#define EFL_CXX_EO_EVENT_HH 7#define EFL_CXX_EO_EVENT_HH
8 8
9#include <Eo.h> 9#include <Eo.h>
10#include <Ecore.h>
10 11
11#include <functional> 12#include <functional>
12#include <memory> 13#include <memory>
@@ -95,7 +96,13 @@ struct _event_deleter
95 void operator()() const 96 void operator()() const
96 { 97 {
97 eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data)); 98 eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data));
98 delete _data; 99 ::ecore_main_loop_thread_safe_call_async(&_deleter_call, _data);
100 }
101
102private:
103 static void _deleter_call(void* data)
104 {
105 delete static_cast<F*>(data);
99 } 106 }
100 107
101 F* _data; 108 F* _data;
diff --git a/src/tests/eolian_cxx/eolian_cxx_test_callback.cc b/src/tests/eolian_cxx/eolian_cxx_test_callback.cc
index 2acfd09..42caa4a 100644
--- a/src/tests/eolian_cxx/eolian_cxx_test_callback.cc
+++ b/src/tests/eolian_cxx/eolian_cxx_test_callback.cc
@@ -10,6 +10,11 @@
10 10
11#include <check.h> 11#include <check.h>
12 12
13#include <iostream>
14#include <vector>
15#include <algorithm>
16#include <functional>
17
13void foo(void*) {} 18void foo(void*) {}
14 19
15START_TEST(eolian_cxx_test_callback_method) 20START_TEST(eolian_cxx_test_callback_method)
@@ -121,6 +126,54 @@ START_TEST(eolian_cxx_test_global_callback)
121} 126}
122END_TEST 127END_TEST
123 128
129START_TEST(eolian_cxx_test_disconnect_inside_callback)
130{
131 efl::eo::eo_init i;
132 callback c;
133
134 std::vector<long> capture_me;
135 int times_called = 0;
136
137 ::efl::eo::signal_connection sig(nullptr);
138 sig = c.callback_callback_add_add(
139 std::bind([&sig, &capture_me, &times_called](void *info)
140 {
141 ++times_called;
142 std::cout << "times_called: " << times_called << std::endl;
143 std::cout << "&sig: " << &sig << std::endl;
144 if (times_called <= 1)
145 return;
146
147 sig.disconnect();
148
149 long* info_l = static_cast<long*>(info);
150 std::cout << "info: " << info << std::endl;
151 std::cout << "*info_l: " << *info_l << std::endl;
152
153 fail_if(*info_l != 42);
154
155 capture_me = {9, 0, 8, 1, 7, 2, 6, 3, 5, 4};
156 std::sort(capture_me.begin(), capture_me.end());
157
158 capture_me[0] = capture_me[1] + +capture_me[2] + capture_me[9];
159
160 std::cout << "&capture_me: " << &capture_me << std::endl;
161 std::cout << "capture_me [0] [9]: [" << capture_me[0] << "] ["<< capture_me[9] << "]" << std::endl;
162
163 fail_if(capture_me.size() != 10);
164 fail_if(capture_me[0] != 12);
165 fail_if(times_called != 2);
166 }, std::placeholders::_3));
167
168 long n = 42;
169 c.callback_callback_add_call(&n);
170
171 fail_if(capture_me.size() != 10);
172 fail_if(capture_me[0] != 12);
173 fail_if(times_called != 2);
174}
175END_TEST
176
124void 177void
125eolian_cxx_test_callback(TCase* tc) 178eolian_cxx_test_callback(TCase* tc)
126{ 179{
@@ -128,4 +181,5 @@ eolian_cxx_test_callback(TCase* tc)
128 tcase_add_test(tc, eolian_cxx_test_callback_event_add); 181 tcase_add_test(tc, eolian_cxx_test_callback_event_add);
129 tcase_add_test(tc, eolian_cxx_test_callback_event_del); 182 tcase_add_test(tc, eolian_cxx_test_callback_event_del);
130 tcase_add_test(tc, eolian_cxx_test_global_callback); 183 tcase_add_test(tc, eolian_cxx_test_global_callback);
184 tcase_add_test(tc, eolian_cxx_test_disconnect_inside_callback);
131} 185}