diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index fd38e3493..4ea256974 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -230,6 +230,10 @@ EXTRA_DIST = \ sigalrm.vgtest \ sigaltstack.stderr.exp \ sigaltstack.vgtest \ + std_list.stderr.exp \ + std_list.vgtest \ + std_string.stderr.exp \ + std_string.vgtest \ std_thread.stderr.exp \ std_thread.vgtest \ tc01_simple_race.stderr.exp \ @@ -370,6 +374,8 @@ endif if CXX_CAN_INCLUDE_THREAD_HEADER if HAVE_SHARED_POINTER_ANNOTATION check_PROGRAMS += \ + std_list \ + std_string \ std_thread endif endif @@ -450,6 +456,12 @@ if HAVE_PTHREAD_BARRIER matinv_LDADD = $(LDADD) -lm endif +std_list_SOURCES = std_list.cpp +std_list_CXXFLAGS = $(AM_CXXFLAGS) -std=c++0x -Wno-sign-compare + +std_string_SOURCES = std_string.cpp +std_string_CXXFLAGS = $(AM_CXXFLAGS) -std=c++0x -Wno-sign-compare + std_thread_SOURCES = std_thread.cpp std_thread_CXXFLAGS = $(AM_CXXFLAGS) -std=c++0x diff --git a/drd/tests/std_list.cpp b/drd/tests/std_list.cpp new file mode 100644 index 000000000..1f0916453 --- /dev/null +++ b/drd/tests/std_list.cpp @@ -0,0 +1,99 @@ +/* + * Test program that triggers strcpy() from one thread and a memory allocation + * immediately after the region read by strcpy() from another thread. Without + * strcpy() intercept there is about 50% chance that this test program triggers + * a false positive race report on Ubuntu 12.10 amd64. + * + * See also https://bugs.kde.org/show_bug.cgi?id=326436. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class SubTest { +public: + SubTest() { + list ffList; + ffList.push_back((int *) NULL); + for (list::iterator ff = ffList.begin(); ff != ffList.end(); ff++) { + usleep(1000); + } + } + void subTest() { + list ffList; + ffList.push_back((int *) NULL); + for (list::const_iterator ff = ffList.begin(); ff != ffList.end(); ff++) { + usleep(1000); + } + } +}; + +class Test { + SubTest *subTest; +public: + void setUp() { + subTest = new SubTest(); + setlocale(LC_ALL, "English"); + } + void tearDown() { + delete subTest; } + void func1() { + for (size_t i = 0; i < 10000; i++) { + subTest->subTest(); + usleep(1000); + } + } + void func2() { + usleep(1000); + } +}; + +void *func1(void *instance) +{ + Test *casted = reinterpret_cast(instance); + casted->setUp(); + casted->func1(); + casted->tearDown(); + return NULL; +} + +void *func2(void *instance) +{ + Test *casted = reinterpret_cast(instance); + casted->setUp(); + casted->func2(); + casted->tearDown(); + return NULL; +} + +int main(int argc, char* argv[]) +{ + int err; + pthread_t thread1; + pthread_t thread2; + Test instance1; + Test instance2; + + // create + err = pthread_create(&thread1, NULL, &func1, &instance1); + if (err != 0) + throw string("failed to create a thread."); + err = pthread_create(&thread2, NULL, &func2, &instance2); + if (err != 0) + throw string("failed to create a thread."); + // join + err = pthread_join(thread1, NULL); + if (err != 0) + throw string("Thread::join(): failed to join."); + err = pthread_join(thread2, NULL); + if (err != 0) + throw string("Thread::join(): failed to join."); +} diff --git a/drd/tests/std_list.stderr.exp b/drd/tests/std_list.stderr.exp new file mode 100644 index 000000000..d18786f80 --- /dev/null +++ b/drd/tests/std_list.stderr.exp @@ -0,0 +1,3 @@ + + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/drd/tests/std_list.vgtest b/drd/tests/std_list.vgtest new file mode 100644 index 000000000..11531a5c3 --- /dev/null +++ b/drd/tests/std_list.vgtest @@ -0,0 +1,4 @@ +prereq: test -e std_list && ./supported_libpthread +vgopts: --check-stack-var=yes --show-confl-seg=no +prog: std_list +stderr_filter: filter_stderr diff --git a/drd/tests/std_string.cpp b/drd/tests/std_string.cpp new file mode 100644 index 000000000..8a35fb3d5 --- /dev/null +++ b/drd/tests/std_string.cpp @@ -0,0 +1,67 @@ +/* + * Test program that uses std::string object from more than one thread and + * that also triggers a call to __GI_strlen() (from inside strdup()). See also + * https://bugs.kde.org/show_bug.cgi?id=326091. + */ + +#include +#include +#include +#include +#include + +char* list2byteArray() +{ + size_t data_size = 24; + char *data = new char[data_size]; + for (size_t i = 0; i < data_size; i++) + data[i] = 'a'; + data[data_size - 1] = 0; + char *ret = strdup(data); + delete[] data; + return ret; +} + +int addRecord() +{ + char *data = list2byteArray(); + usleep(100); + free(data); + return 0; +} + +void *fillTable(void *ptr) +{ + for (int i = 0; i < 100; i++) { + std::string id("000"); + id.append(1, 'a' + i); + std::list record; + record.push_back("some data"); + addRecord(); + } + usleep(1000 * 1000); + return NULL; +} + +int main(int argc, char* argv[]) +{ + pthread_t thread[2]; + + for (int i = 0; i < sizeof(thread)/sizeof(thread[0]); i++) { + int ret = pthread_create(&thread[i], NULL, &fillTable, NULL); + if (ret) { + fprintf(stderr, "Failed to create thread %d: %d\n", i, ret); + return 1; + } + } + + for (int i = 0; i < sizeof(thread)/sizeof(thread[0]); i++) { + int ret = pthread_join(thread[i], NULL); + if (ret != 0) { + fprintf(stderr, "Failed to join thread %d: %d\n", i, ret); + return 1; + } + } + + return 0; +} diff --git a/drd/tests/std_string.stderr.exp b/drd/tests/std_string.stderr.exp new file mode 100644 index 000000000..d18786f80 --- /dev/null +++ b/drd/tests/std_string.stderr.exp @@ -0,0 +1,3 @@ + + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/drd/tests/std_string.vgtest b/drd/tests/std_string.vgtest new file mode 100644 index 000000000..fec4ea4c1 --- /dev/null +++ b/drd/tests/std_string.vgtest @@ -0,0 +1,4 @@ +prereq: test -e std_string && ./supported_libpthread +vgopts: --check-stack-var=yes --show-confl-seg=no +prog: std_string +stderr_filter: filter_stderr