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
19using namespace std;
20
21class SubTest {
22public:
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
39class Test {
40  SubTest *subTest;
41public:
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
59void *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
68void *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
77int 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}
100