forked from enlightenment/efl
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.
This commit is contained in:
parent
3b441cdf4a
commit
5043dcb830
|
@ -64,6 +64,7 @@ tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
|
||||||
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_cxx\" \
|
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eina_cxx\" \
|
||||||
@CHECK_CFLAGS@ \
|
@CHECK_CFLAGS@ \
|
||||||
@EO_CFLAGS@ \
|
@EO_CFLAGS@ \
|
||||||
|
@ECORE_CFLAGS@ \
|
||||||
@EO_CXX_CFLAGS@ \
|
@EO_CXX_CFLAGS@ \
|
||||||
@EINA_CXX_CFLAGS@
|
@EINA_CXX_CFLAGS@
|
||||||
tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
|
tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@
|
||||||
|
|
|
@ -118,7 +118,7 @@ tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
|
||||||
tests_eolian_cxx_eolian_cxx_suite_CFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
|
tests_eolian_cxx_eolian_cxx_suite_CFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
|
||||||
tests_eolian_cxx_eolian_cxx_suite_CPPFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
|
tests_eolian_cxx_eolian_cxx_suite_CPPFLAGS = ${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
|
||||||
tests_eolian_cxx_eolian_cxx_suite_LDADD = \
|
tests_eolian_cxx_eolian_cxx_suite_LDADD = \
|
||||||
@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_EOLIAN_LIBS@
|
@CHECK_LIBS@ @USE_EO_LIBS@ @USE_EINA_LIBS@ @USE_ECORE_LIBS@ @USE_EOLIAN_LIBS@
|
||||||
tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
|
tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define EFL_CXX_EO_EVENT_HH
|
#define EFL_CXX_EO_EVENT_HH
|
||||||
|
|
||||||
#include <Eo.h>
|
#include <Eo.h>
|
||||||
|
#include <Ecore.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -95,7 +96,13 @@ struct _event_deleter
|
||||||
void operator()() const
|
void operator()() const
|
||||||
{
|
{
|
||||||
eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data));
|
eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data));
|
||||||
delete _data;
|
::ecore_main_loop_thread_safe_call_async(&_deleter_call, _data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void _deleter_call(void* data)
|
||||||
|
{
|
||||||
|
delete static_cast<F*>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
F* _data;
|
F* _data;
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
void foo(void*) {}
|
void foo(void*) {}
|
||||||
|
|
||||||
START_TEST(eolian_cxx_test_callback_method)
|
START_TEST(eolian_cxx_test_callback_method)
|
||||||
|
@ -121,6 +126,54 @@ START_TEST(eolian_cxx_test_global_callback)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(eolian_cxx_test_disconnect_inside_callback)
|
||||||
|
{
|
||||||
|
efl::eo::eo_init i;
|
||||||
|
callback c;
|
||||||
|
|
||||||
|
std::vector<long> capture_me;
|
||||||
|
int times_called = 0;
|
||||||
|
|
||||||
|
::efl::eo::signal_connection sig(nullptr);
|
||||||
|
sig = c.callback_callback_add_add(
|
||||||
|
std::bind([&sig, &capture_me, ×_called](void *info)
|
||||||
|
{
|
||||||
|
++times_called;
|
||||||
|
std::cout << "times_called: " << times_called << std::endl;
|
||||||
|
std::cout << "&sig: " << &sig << std::endl;
|
||||||
|
if (times_called <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sig.disconnect();
|
||||||
|
|
||||||
|
long* info_l = static_cast<long*>(info);
|
||||||
|
std::cout << "info: " << info << std::endl;
|
||||||
|
std::cout << "*info_l: " << *info_l << std::endl;
|
||||||
|
|
||||||
|
fail_if(*info_l != 42);
|
||||||
|
|
||||||
|
capture_me = {9, 0, 8, 1, 7, 2, 6, 3, 5, 4};
|
||||||
|
std::sort(capture_me.begin(), capture_me.end());
|
||||||
|
|
||||||
|
capture_me[0] = capture_me[1] + +capture_me[2] + capture_me[9];
|
||||||
|
|
||||||
|
std::cout << "&capture_me: " << &capture_me << std::endl;
|
||||||
|
std::cout << "capture_me [0] [9]: [" << capture_me[0] << "] ["<< capture_me[9] << "]" << std::endl;
|
||||||
|
|
||||||
|
fail_if(capture_me.size() != 10);
|
||||||
|
fail_if(capture_me[0] != 12);
|
||||||
|
fail_if(times_called != 2);
|
||||||
|
}, std::placeholders::_3));
|
||||||
|
|
||||||
|
long n = 42;
|
||||||
|
c.callback_callback_add_call(&n);
|
||||||
|
|
||||||
|
fail_if(capture_me.size() != 10);
|
||||||
|
fail_if(capture_me[0] != 12);
|
||||||
|
fail_if(times_called != 2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
eolian_cxx_test_callback(TCase* tc)
|
eolian_cxx_test_callback(TCase* tc)
|
||||||
{
|
{
|
||||||
|
@ -128,4 +181,5 @@ eolian_cxx_test_callback(TCase* tc)
|
||||||
tcase_add_test(tc, eolian_cxx_test_callback_event_add);
|
tcase_add_test(tc, eolian_cxx_test_callback_event_add);
|
||||||
tcase_add_test(tc, eolian_cxx_test_callback_event_del);
|
tcase_add_test(tc, eolian_cxx_test_callback_event_del);
|
||||||
tcase_add_test(tc, eolian_cxx_test_global_callback);
|
tcase_add_test(tc, eolian_cxx_test_global_callback);
|
||||||
|
tcase_add_test(tc, eolian_cxx_test_disconnect_inside_callback);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue