1
0
forked from drath/libratbag

Fix the ref/unref dependency

The current code has the profile ref the device, but the device has no back-ref to
the profile. The following code will free the profile from underneath the
client, despite the caller still having a valid ref:

p = ratbag_device_get_profile_by_index(device, 0);
ratbag_profile_ref(p);
ratbag_device_unref(device);

Fix this by not using refs internally. After probe, the device is static
anyway, so the various refs internally aren't needed. Instead, we also ref/unref
the parent struct whenever we ref/unref a struct. Thus, whenevever the device
refcount reaches zero, we know the caller has no ref active.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2015-09-04 12:56:08 +10:00
parent 409fd9abca
commit dc24ae3aaa
2 changed files with 95 additions and 15 deletions

View File

@@ -133,6 +133,44 @@ START_TEST(device_init)
}
END_TEST
#define ref_unref_test(T, a) \
{ \
int i; \
struct T *tmp = NULL; \
\
for (i = 0; i < 1000; i++) { \
tmp = T##_ref(a); \
ck_assert(tmp == a); \
} \
for (i = 0; i < 1000; i++) { \
tmp = T##_unref(a); \
ck_assert(tmp == a); \
} \
for (i = 0; i < 1000; i++) { \
tmp = T##_ref(a); \
ck_assert(tmp == a); \
tmp = T##_unref(a); \
ck_assert(tmp == a); \
} \
}
START_TEST(device_ref_unref)
{
struct ratbag *r;
struct ratbag_device *d;
struct ratbag_test_device td = sane_device;
r = ratbag_create_context(&abort_iface, NULL);
d = ratbag_device_new_test_device(r, &td);
ck_assert(d != NULL);
ref_unref_test(ratbag_device, d);
ratbag_device_unref(d);
ratbag_unref(r);
}
END_TEST
START_TEST(device_profiles)
{
struct ratbag *r;
@@ -169,6 +207,27 @@ START_TEST(device_profiles)
}
END_TEST
START_TEST(device_profiles_ref_unref)
{
struct ratbag *r;
struct ratbag_device *d;
struct ratbag_profile *p;
struct ratbag_test_device td = sane_device;
r = ratbag_create_context(&abort_iface, NULL);
d = ratbag_device_new_test_device(r, &td);
p = ratbag_device_get_profile_by_index(d, 1);
ref_unref_test(ratbag_profile, p);
ratbag_device_unref(d);
ratbag_profile_unref(p);
ratbag_unref(r);
}
END_TEST
START_TEST(device_profiles_num_0)
{
struct ratbag *r;
@@ -348,10 +407,12 @@ test_context_suite(void)
s = suite_create("device");
tc = tcase_create("device");
tcase_add_test(tc, device_init);
tcase_add_test(tc, device_ref_unref);
suite_add_tcase(s, tc);
tc = tcase_create("profiles");
tcase_add_test(tc, device_profiles);
tcase_add_test(tc, device_profiles_ref_unref);
tcase_add_test(tc, device_profiles_num_0);
tcase_add_test(tc, device_profiles_multiple_active);
tcase_add_test(tc, device_profiles_get_invalid);