diff options
author | Simon McVittie <smcv@collabora.com> | 2023-01-09 12:45:44 +0000 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2023-01-09 12:45:44 +0000 |
commit | d9fcc508f2374dc76b729663678dd9e9e13f269c (patch) | |
tree | 1401feee7f052cfb3a0a958b6b0f281f7f70eaa8 | |
parent | 79f7fcab69ec13fdb66deb9ca4d58f9565de82db (diff) | |
parent | 68bd64d63c6b518eadc1458d7ec0952afb5f256f (diff) | |
download | dbus-d9fcc508f2374dc76b729663678dd9e9e13f269c.tar.gz |
Merge branch '1.14-backports' into 'dbus-1.14'
[1.14.x] Backport: Fix data race with members of struct DBusCounter
See merge request dbus/dbus!384
-rw-r--r-- | dbus/dbus-resources.c | 12 | ||||
-rw-r--r-- | dbus/dbus-resources.h | 8 | ||||
-rw-r--r-- | test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/Makefile.am | 11 | ||||
-rw-r--r-- | test/internals/counter.c | 120 |
5 files changed, 149 insertions, 3 deletions
diff --git a/dbus/dbus-resources.c b/dbus/dbus-resources.c index 9ed663ad..97084a78 100644 --- a/dbus/dbus-resources.c +++ b/dbus/dbus-resources.c @@ -273,7 +273,11 @@ _dbus_counter_adjust_unix_fd (DBusCounter *counter, long _dbus_counter_get_size_value (DBusCounter *counter) { - return counter->size_value; + long result; + _dbus_rmutex_lock (counter->mutex); + result = counter->size_value; + _dbus_rmutex_unlock (counter->mutex); + return result; } /** @@ -285,7 +289,11 @@ _dbus_counter_get_size_value (DBusCounter *counter) long _dbus_counter_get_unix_fd_value (DBusCounter *counter) { - return counter->unix_fd_value; + long result; + _dbus_rmutex_lock (counter->mutex); + result = counter->unix_fd_value; + _dbus_rmutex_unlock (counter->mutex); + return result; } /** diff --git a/dbus/dbus-resources.h b/dbus/dbus-resources.h index 9ac4d334..dd9221ce 100644 --- a/dbus/dbus-resources.h +++ b/dbus/dbus-resources.h @@ -23,6 +23,7 @@ #ifndef DBUS_RESOURCES_H #define DBUS_RESOURCES_H +#include <dbus/dbus-internals.h> #include <dbus/dbus-macros.h> #include <dbus/dbus-errors.h> #include <dbus/dbus-connection.h> @@ -33,17 +34,22 @@ typedef struct DBusCounter DBusCounter; typedef void (* DBusCounterNotifyFunction) (DBusCounter *counter, void *user_data); - +DBUS_EMBEDDED_TESTS_EXPORT DBusCounter* _dbus_counter_new (void); DBusCounter* _dbus_counter_ref (DBusCounter *counter); +DBUS_EMBEDDED_TESTS_EXPORT void _dbus_counter_unref (DBusCounter *counter); +DBUS_EMBEDDED_TESTS_EXPORT void _dbus_counter_adjust_size (DBusCounter *counter, long delta); +DBUS_EMBEDDED_TESTS_EXPORT void _dbus_counter_adjust_unix_fd (DBusCounter *counter, long delta); void _dbus_counter_notify (DBusCounter *counter); +DBUS_EMBEDDED_TESTS_EXPORT long _dbus_counter_get_size_value (DBusCounter *counter); +DBUS_EMBEDDED_TESTS_EXPORT long _dbus_counter_get_unix_fd_value (DBusCounter *counter); void _dbus_counter_set_notify (DBusCounter *counter, diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e71c8f73..494ca4ae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -158,6 +158,7 @@ if(DBUS_ENABLE_EMBEDDED_TESTS) if(NOT WIN32) add_test_executable(test-bus-system bus/system.c launch-helper-internal dbus-testutils) + add_test_executable(test-counter internals/counter.c dbus-testutils) if(ENABLE_TRADITIONAL_ACTIVATION) add_test_executable(test-bus-launch-helper-oom bus/launch-helper-oom.c launch-helper-internal dbus-testutils) add_helper_executable(dbus-daemon-launch-helper-for-tests bus/launch-helper-for-tests.c launch-helper-internal) diff --git a/test/Makefile.am b/test/Makefile.am index 5ffc4e00..5c4d2d0e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -93,6 +93,9 @@ uninstallable_test_programs += \ $(NULL) if DBUS_UNIX +test_counter_SOURCES = internals/counter.c +test_counter_LDADD = libdbus-testutils.la + if ENABLE_TRADITIONAL_ACTIVATION uninstallable_test_programs += test-bus-launch-helper-oom uninstallable_test_programs += test-bus-system @@ -355,6 +358,14 @@ installable_manual_tests += \ $(NULL) endif DBUS_WITH_GLIB +if DBUS_UNIX +if DBUS_ENABLE_EMBEDDED_TESTS +installable_tests += \ + test-counter \ + $(NULL) +endif DBUS_ENABLE_EMBEDDED_TESTS +endif DBUS_UNIX + installable_test_meta = \ $(dist_installable_test_scripts:=.test) \ $(dist_installed_test_scripts:=.test) \ diff --git a/test/internals/counter.c b/test/internals/counter.c new file mode 100644 index 00000000..f46ce5e5 --- /dev/null +++ b/test/internals/counter.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 Ralf Habacker + * SPDX-License-Identifier: MIT + */ + +#include <config.h> + +#include "dbus/dbus-resources.h" +#include "dbus/dbus-test.h" +#include "dbus/dbus-test-tap.h" +#include "test/test-utils.h" + +#include <pthread.h> + +static dbus_bool_t verbose = FALSE; +static DBusCounter *counter = NULL; + +static void* unix_fd_thread1 (void *arg _DBUS_GNUC_UNUSED) +{ + long i; + for (i=0; i < 10000; i++) + { + long j; + _dbus_counter_adjust_unix_fd (counter, 1); + j = _dbus_counter_get_unix_fd_value (counter); + if (verbose) + _dbus_test_diag ("write %ld\n", j); + } + return NULL; +} + +static void* unix_fd_thread2 (void *arg _DBUS_GNUC_UNUSED) +{ + long j = 0; + do + { + j = _dbus_counter_get_unix_fd_value (counter); + if (verbose) + _dbus_test_diag ("read %ld\n", j); + } while (j < 10000); + return NULL; +} + +static void* size_value_thread1 (void *arg _DBUS_GNUC_UNUSED) +{ + long i; + for (i=0; i < 10000; i++) + { + long j; + _dbus_counter_adjust_size (counter, 1); + j = _dbus_counter_get_size_value (counter); + if (verbose) + _dbus_test_diag ("write %ld\n", j); + } + return NULL; +} + +static void* size_value_thread2 (void *arg _DBUS_GNUC_UNUSED) +{ + long j = 0; + do + { + j = _dbus_counter_get_size_value (counter); + if (verbose) + _dbus_test_diag("read %ld\n", j); + } while (j < 10000); + return NULL; +} + +static dbus_bool_t +_dbus_counter_unix_fd_test (const char *test_data_dir _DBUS_GNUC_UNUSED) +{ + pthread_t tid[2]; + dbus_bool_t ret = TRUE; + counter = _dbus_counter_new (); + + pthread_create (&(tid[0]), NULL, &unix_fd_thread1, NULL); + pthread_create (&(tid[1]), NULL, &unix_fd_thread2, NULL); + + pthread_join (tid[0], NULL); + pthread_join (tid[1], NULL); + + _dbus_counter_unref (counter); + + return ret; +} + +static dbus_bool_t +_dbus_counter_size_value_test (const char *test_data_dir _DBUS_GNUC_UNUSED) +{ + pthread_t tid[2]; + dbus_bool_t ret = TRUE; + counter = _dbus_counter_new (); + + pthread_create (&(tid[0]), NULL, &size_value_thread1, NULL); + pthread_create (&(tid[1]), NULL, &size_value_thread2, NULL); + + pthread_join (tid[0], NULL); + pthread_join (tid[1], NULL); + + _dbus_counter_unref (counter); + + return ret; +} + +static const DBusTestCase test[] = +{ + { "unix_fd", _dbus_counter_unix_fd_test }, + { "size", _dbus_counter_size_value_test }, +}; + + +int +main (int argc, + char **argv) +{ + return _dbus_test_main (argc, argv, sizeof(test) / sizeof (DBusTestCase), test, + DBUS_TEST_FLAGS_CHECK_MEMORY_LEAKS, + NULL, NULL); +} |