Added a routine to cause a deadlock. See http://wiki.dlma.com/gdb for more.
David Blume

David Blume commited on 2016-10-16 20:24:34
Showing 11 changed files, with 111 additions and 26 deletions.

... ...
@@ -9,10 +9,13 @@ $(SUBDIRS):
9 9
 	$(MAKE) -C $@
10 10
 
11 11
 all: $(LIBDIR) subdirs
12
+	for dir in $(SUBDIRS); do \
13
+		$(MAKE) -C $$dir \
14
+	done
12 15
 
13 16
 debug:
14 17
 	for dir in $(SUBDIRS); do \
15
-		$(MAKE) -C $$dir debug; \
18
+		$(MAKE) -C $$dir $(MAKECMDGOALS); \
16 19
 	done
17 20
 
18 21
 product: my_lib
... ...
@@ -22,5 +25,5 @@ $(LIBDIR):
22 25
 
23 26
 clean:
24 27
 	for dir in $(SUBDIRS); do \
25
-		$(MAKE) -C $$dir clean; \
28
+		$(MAKE) -C $$dir $(MAKECMDGOALS); \
26 29
 	done
... ...
@@ -12,7 +12,7 @@ LIB=$(LIBDIR)/libmy_lib.a
12 12
 
13 13
 all: $(LIB)
14 14
 
15
-debug: CPPFLAGS += -g
15
+debug: CPPFLAGS += -DDEBUG -ggdb
16 16
 debug: $(LIB)
17 17
 
18 18
 $(OBJDIR):
... ...
@@ -6,14 +6,14 @@ LDFLAGS=-pthread -L $(LIBDIR) -lmy_lib
6 6
 OBJDIR=obj
7 7
 
8 8
 SOURCES=main.cpp main_helper.cpp ui/widget.cpp scoped_set_adder.cpp \
9
-	thread_with_lambda.cpp thread_manager.cpp
9
+	thread_with_lambda.cpp thread_manager.cpp deadlock/deadlock.cpp
10 10
 # //OBJECTS=$(OBJDIR)$(SOURCES:.cpp=.o)
11 11
 OBJECTS=$(foreach bname, $(basename $(SOURCES)), $(OBJDIR)/$(bname).o)
12
-EXECUTABLE=main
12
+EXECUTABLE=testcode
13 13
 
14 14
 all: $(EXECUTABLE)
15 15
 
16
-debug: CPPFLAGS += -g
16
+debug: CPPFLAGS += -DDEBUG -ggdb
17 17
 debug: $(EXECUTABLE)
18 18
 
19 19
 $(OBJDIR):
... ...
@@ -22,10 +22,13 @@ $(OBJDIR):
22 22
 $(OBJDIR)/ui:
23 23
 	mkdir $@
24 24
 
25
+$(OBJDIR)/deadlock:
26
+	mkdir $@
27
+
25 28
 $(EXECUTABLE): $(OBJECTS) $(LIBDIR)/libmy_lib.a
26 29
 	$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
27 30
 
28
-$(OBJDIR)/%.o: %.cpp ../include/my_lib.hpp | $(OBJDIR) $(OBJDIR)/ui
31
+$(OBJDIR)/%.o: %.cpp ../include/my_lib.hpp | $(OBJDIR) $(OBJDIR)/ui $(OBJDIR)/deadlock
29 32
 	$(CXX) $(CPPFLAGS) $< -o $@
30 33
 
31 34
 clean:
... ...
@@ -0,0 +1,85 @@
1
+#include <iostream>
2
+#include <string>
3
+#include <vector>
4
+#include <thread>
5
+#include <mutex>
6
+#include <unistd.h>
7
+#include <random>
8
+#include <chrono>
9
+#include "deadlock.hpp"
10
+
11
+using namespace std;
12
+
13
+namespace {
14
+
15
+std::mutex left_chopstick;
16
+std::mutex right_chopstick;
17
+
18
+std::vector<std::thread> workers;
19
+
20
+void do_work_on_right(bool, int32_t);
21
+
22
+int get_rnd()
23
+{
24
+    static std::random_device rd;
25
+    static std::mt19937 gen(rd());
26
+    static std::uniform_int_distribution<> dis(100, 200);
27
+    return dis(gen);
28
+}
29
+
30
+void do_work_on_left(bool have_right, int32_t tick)
31
+{
32
+    std::lock_guard<std::mutex> lm (left_chopstick);
33
+    std::this_thread::sleep_for(std::chrono::milliseconds(get_rnd()));
34
+    if (have_right) {
35
+        std::cout << "deadlock::thread " << std::hex << this_thread::get_id() << " " << tick << endl;
36
+    } else {
37
+        do_work_on_right(true, tick);
38
+    }
39
+}
40
+
41
+void do_work_on_right(bool have_left, int32_t tick)
42
+{
43
+    std::lock_guard<std::mutex> rm (right_chopstick);
44
+    std::this_thread::sleep_for(std::chrono::milliseconds(get_rnd()));
45
+    if (have_left) {
46
+        std::cout << "deadlock::thread " << std::hex << this_thread::get_id() << " " << tick << endl;
47
+    } else {
48
+        do_work_on_left(true, tick);
49
+    }
50
+}
51
+
52
+void work(int32_t ticks)
53
+{
54
+    for(int32_t tick = ticks; tick >= 0; tick--) {
55
+        do_work_on_right(false, tick);
56
+    }
57
+}
58
+
59
+};
60
+
61
+int deadlock()
62
+{
63
+    uint32_t ticks = 10;
64
+    cout << "The function " << __PRETTY_FUNCTION__ << " was called." << endl;
65
+    cerr << "WARNING: Expect a deadlock. See http://wiki.dlma.com/gdb" << endl;
66
+
67
+    // Construct the thread right into the push_back() call.
68
+    workers.push_back(std::thread([=]{
69
+        for(uint32_t tick = 0; tick <= ticks; tick++) {
70
+            do_work_on_left(false, tick);
71
+            // usleep(get_rnd() * 1000);  // u for microseconds
72
+        }
73
+    }));
74
+
75
+    // Or, move the thread into the array.
76
+    std::thread t2(work, ticks);
77
+    workers.push_back(move(t2));
78
+
79
+    // Don't return before the other threads have finished.
80
+    for (auto &w : workers) {
81
+        if (w.joinable()) w.join();
82
+    }
83
+    return 0;
84
+}
85
+
... ...
@@ -0,0 +1,4 @@
1
+#pragma once
2
+
3
+int deadlock();
4
+
... ...
@@ -11,6 +11,7 @@
11 11
 #include "../include/my_lib.hpp"
12 12
 #include "thread_with_lambda.hpp"
13 13
 #include "thread_manager.hpp"
14
+#include "deadlock/deadlock.hpp"
14 15
  
15 16
 using namespace std;
16 17
  
... ...
@@ -116,6 +117,8 @@ int main() {
116 117
         my_class->f();
117 118
     }
118 119
 
120
+    deadlock();
121
+
119 122
     // This_function_is_not_defined();
120 123
  
121 124
     cout << "Done." << endl;
... ...
@@ -1,5 +1,4 @@
1
-#ifndef __main_helper_hpp
2
-#define __main_helper_hpp
1
+#pragma once
3 2
 #include <memory>
4 3
 
5 4
 int main_helper_fn();
... ...
@@ -22,6 +21,3 @@ public:
22 21
     class Impl;  // defined in cpp
23 22
     Pimpl<Impl> pimpl;
24 23
 };
25
-
26
-
27
-#endif
... ...
@@ -1,5 +1,4 @@
1
-#ifndef scoped_set_adder_h_
2
-#define scoped_set_adder_h_
1
+#pragma once
3 2
 
4 3
 #include <string>
5 4
  
... ...
@@ -15,5 +14,3 @@ public:
15 14
 private:
16 15
     std::string name_;
17 16
 };
18
- 
19
-#endif
... ...
@@ -1,5 +1,4 @@
1
-#ifndef thread_manager_hpp_
2
-#define thread_manager_hpp_
1
+#pragma once
3 2
 
4 3
 #include <mutex>
5 4
 #include <condition_variable>
... ...
@@ -21,5 +20,3 @@ struct Manager {
21 20
     std::thread report_thread_;
22 21
 	int data_to_protect_;
23 22
 };
24
-
25
-#endif
... ...
@@ -15,11 +15,11 @@ void thread_with_lambda()
15 15
 {
16 16
     uint32_t ticks = 10;
17 17
     std::lock_guard<std::mutex> lock(my_mutex);
18
-    if (worker.joinable()) worker.join();
19 18
 
20 19
     worker = std::thread([=]{
21 20
         for(uint32_t tick = 0; tick <= ticks; tick++) {
22
-            std::cout << "count " << tick << std::endl;
21
+            std::cout << __PRETTY_FUNCTION__ << " count " << tick << std::endl;
23 22
         }
24 23
     });
24
+    if (worker.joinable()) worker.join();
25 25
 }
... ...
@@ -1,6 +1,3 @@
1
-#ifndef thread_with_lambda_hpp_
2
-#define thread_with_lambda_hpp_
1
+#pragma once
3 2
 
4 3
 void thread_with_lambda();
5
-
6
-#endif
7 4