bart | 4115c71 | 2013-10-23 12:37:44 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Test program that triggers strcpy() from one thread and a memory allocation |
| 3 | * immediately after the region read by strcpy() from another thread. Without |
| 4 | * strcpy() intercept there is about 50% chance that this test program triggers |
| 5 | * a false positive race report on Ubuntu 12.10 amd64. |
| 6 | * |
| 7 | * See also https://bugs.kde.org/show_bug.cgi?id=326436. |
| 8 | */ |
| 9 | |
| 10 | #include <locale.h> |
| 11 | #include <stdlib.h> |
| 12 | #include <unistd.h> |
| 13 | #include <pthread.h> |
| 14 | #include <string.h> |
| 15 | #include <string> |
| 16 | #include <sstream> |
| 17 | #include <list> |
| 18 | |
| 19 | using namespace std; |
| 20 | |
| 21 | class SubTest { |
| 22 | public: |
| 23 | SubTest() { |
| 24 | list<int *> ffList; |
| 25 | ffList.push_back((int *) NULL); |
| 26 | for (list<int*>::iterator ff = ffList.begin(); ff != ffList.end(); ff++) { |
| 27 | usleep(1000); |
| 28 | } |
| 29 | } |
| 30 | void subTest() { |
| 31 | list<int *> ffList; |
| 32 | ffList.push_back((int *) NULL); |
| 33 | for (list<int*>::const_iterator ff = ffList.begin(); ff != ffList.end(); ff++) { |
| 34 | usleep(1000); |
| 35 | } |
| 36 | } |
| 37 | }; |
| 38 | |
| 39 | class Test { |
| 40 | SubTest *subTest; |
| 41 | public: |
| 42 | void setUp() { |
| 43 | subTest = new SubTest(); |
| 44 | setlocale(LC_ALL, "English"); |
| 45 | } |
| 46 | void tearDown() { |
| 47 | delete subTest; } |
| 48 | void func1() { |
| 49 | for (size_t i = 0; i < 10000; i++) { |
| 50 | subTest->subTest(); |
| 51 | usleep(1000); |
| 52 | } |
| 53 | } |
| 54 | void func2() { |
| 55 | usleep(1000); |
| 56 | } |
| 57 | }; |
| 58 | |
| 59 | void *func1(void *instance) |
| 60 | { |
| 61 | Test *casted = reinterpret_cast<Test*>(instance); |
| 62 | casted->setUp(); |
| 63 | casted->func1(); |
| 64 | casted->tearDown(); |
| 65 | return NULL; |
| 66 | } |
| 67 | |
| 68 | void *func2(void *instance) |
| 69 | { |
| 70 | Test *casted = reinterpret_cast<Test*>(instance); |
| 71 | casted->setUp(); |
| 72 | casted->func2(); |
| 73 | casted->tearDown(); |
| 74 | return NULL; |
| 75 | } |
| 76 | |
| 77 | int main(int argc, char* argv[]) |
| 78 | { |
| 79 | int err; |
| 80 | pthread_t thread1; |
| 81 | pthread_t thread2; |
| 82 | Test instance1; |
| 83 | Test instance2; |
| 84 | |
| 85 | // create |
| 86 | err = pthread_create(&thread1, NULL, &func1, &instance1); |
| 87 | if (err != 0) |
| 88 | throw string("failed to create a thread."); |
| 89 | err = pthread_create(&thread2, NULL, &func2, &instance2); |
| 90 | if (err != 0) |
| 91 | throw string("failed to create a thread."); |
| 92 | // join |
| 93 | err = pthread_join(thread1, NULL); |
| 94 | if (err != 0) |
| 95 | throw string("Thread::join(): failed to join."); |
| 96 | err = pthread_join(thread2, NULL); |
| 97 | if (err != 0) |
| 98 | throw string("Thread::join(): failed to join."); |
| 99 | } |