1 //===-- main.cpp ------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // This test is intended to create a situation in which multiple events
10 // (breakpoints, watchpoints, crashes, and signal generation/delivery) happen
11 // from multiple threads. The test expects the debugger to set a breakpoint on
12 // the main thread (before any worker threads are spawned) and modify variables
13 // which control the number of threads that are spawned for each action.
14 
15 #include "pseudo_barrier.h"
16 #include <vector>
17 using namespace std;
18 
19 #include <pthread.h>
20 
21 #include <signal.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 typedef std::vector<std::pair<unsigned, void*(*)(void*)> > action_counts;
26 typedef std::vector<pthread_t> thread_vector;
27 
28 pseudo_barrier_t g_barrier;
29 int g_breakpoint = 0;
30 int g_sigusr1_count = 0;
31 uint32_t g_watchme;
32 
33 struct action_args {
34   int delay;
35 };
36 
37 // Perform any extra actions required by thread 'input' arg
38 void do_action_args(void *input) {
39     if (input) {
40       action_args *args = static_cast<action_args*>(input);
41       sleep(args->delay);
42     }
43 }
44 
45 void *
46 breakpoint_func (void *input)
47 {
48     // Wait until all threads are running
49     pseudo_barrier_wait(g_barrier);
50     do_action_args(input);
51 
52     // Do something
53     g_breakpoint++;       // Set breakpoint here
54     return 0;
55 }
56 
57 void *
58 signal_func (void *input) {
59     // Wait until all threads are running
60     pseudo_barrier_wait(g_barrier);
61     do_action_args(input);
62 
63     // Send a user-defined signal to the current process
64     //kill(getpid(), SIGUSR1);
65     // Send a user-defined signal to the current thread
66     pthread_kill(pthread_self(), SIGUSR1);
67 
68     return 0;
69 }
70 
71 void *
72 watchpoint_func (void *input) {
73     pseudo_barrier_wait(g_barrier);
74     do_action_args(input);
75 
76     g_watchme = 1;     // watchpoint triggers here
77     return 0;
78 }
79 
80 void *
81 crash_func (void *input) {
82     pseudo_barrier_wait(g_barrier);
83     do_action_args(input);
84 
85     int *a = 0;
86     *a = 5; // crash happens here
87     return 0;
88 }
89 
90 void sigusr1_handler(int sig) {
91     if (sig == SIGUSR1)
92         g_sigusr1_count += 1; // Break here in signal handler
93 }
94 
95 /// Register a simple function for to handle signal
96 void register_signal_handler(int signal, void (*handler)(int))
97 {
98     sigset_t empty_sigset;
99     sigemptyset(&empty_sigset);
100 
101     struct sigaction action;
102     action.sa_sigaction = 0;
103     action.sa_mask = empty_sigset;
104     action.sa_flags = 0;
105     action.sa_handler = handler;
106     sigaction(SIGUSR1, &action, 0);
107 }
108 
109 void start_threads(thread_vector& threads,
110                    action_counts& actions,
111                    void* args = 0) {
112     action_counts::iterator b = actions.begin(), e = actions.end();
113     for(action_counts::iterator i = b; i != e; ++i) {
114         for(unsigned count = 0; count < i->first; ++count) {
115             pthread_t t;
116             pthread_create(&t, 0, i->second, args);
117             threads.push_back(t);
118         }
119     }
120 }
121 
122 int dotest()
123 {
124     g_watchme = 0;
125 
126     // Actions are triggered immediately after the thread is spawned
127     unsigned num_breakpoint_threads = 1;
128     unsigned num_watchpoint_threads = 0;
129     unsigned num_signal_threads = 1;
130     unsigned num_crash_threads = 0;
131 
132     // Actions below are triggered after a 1-second delay
133     unsigned num_delay_breakpoint_threads = 0;
134     unsigned num_delay_watchpoint_threads = 0;
135     unsigned num_delay_signal_threads = 0;
136     unsigned num_delay_crash_threads = 0;
137 
138     register_signal_handler(SIGUSR1, sigusr1_handler); // Break here and adjust num_[breakpoint|watchpoint|signal|crash]_threads
139 
140     unsigned total_threads = num_breakpoint_threads \
141                              + num_watchpoint_threads \
142                              + num_signal_threads \
143                              + num_crash_threads \
144                              + num_delay_breakpoint_threads \
145                              + num_delay_watchpoint_threads \
146                              + num_delay_signal_threads \
147                              + num_delay_crash_threads;
148 
149     // Don't let either thread do anything until they're both ready.
150     pseudo_barrier_init(g_barrier, total_threads);
151 
152     action_counts actions;
153     actions.push_back(std::make_pair(num_breakpoint_threads, breakpoint_func));
154     actions.push_back(std::make_pair(num_watchpoint_threads, watchpoint_func));
155     actions.push_back(std::make_pair(num_signal_threads, signal_func));
156     actions.push_back(std::make_pair(num_crash_threads, crash_func));
157 
158     action_counts delay_actions;
159     delay_actions.push_back(std::make_pair(num_delay_breakpoint_threads, breakpoint_func));
160     delay_actions.push_back(std::make_pair(num_delay_watchpoint_threads, watchpoint_func));
161     delay_actions.push_back(std::make_pair(num_delay_signal_threads, signal_func));
162     delay_actions.push_back(std::make_pair(num_delay_crash_threads, crash_func));
163 
164     // Create threads that handle instant actions
165     thread_vector threads;
166     start_threads(threads, actions);
167 
168     // Create threads that handle delayed actions
169     action_args delay_arg;
170     delay_arg.delay = 1;
171     start_threads(threads, delay_actions, &delay_arg);
172 
173     // Join all threads
174     typedef std::vector<pthread_t>::iterator thread_iterator;
175     for(thread_iterator t = threads.begin(); t != threads.end(); ++t)
176         pthread_join(*t, 0);
177 
178     return 0;
179 }
180 
181 int main ()
182 {
183     dotest();
184     return 0; // Break here and verify one thread is active.
185 }
186 
187 
188