1#include "pseudo_barrier.h"
2#include "thread.h"
3#include <atomic>
4#include <chrono>
5#include <cinttypes>
6#include <csignal>
7#include <cstdio>
8#include <cstdlib>
9#include <cstring>
10#include <mutex>
11#include <thread>
12#include <unistd.h>
13#include <vector>
14
15pseudo_barrier_t barrier;
16std::mutex print_mutex;
17std::atomic<bool> can_work;
18thread_local volatile sig_atomic_t can_exit_now = false;
19
20static void sigint_handler(int signo) {}
21
22static void sigusr1_handler(int signo) {
23 std::lock_guard<std::mutex> lock{print_mutex};
24 std::printf(format: "received SIGUSR1 on thread id: %" PRIx64 "\n", get_thread_id());
25 can_exit_now = true;
26}
27
28static void thread_func() {
29 // this ensures that all threads start before we stop
30 pseudo_barrier_wait(barrier);
31
32 // wait till the main thread indicates that we can go
33 // (note: using a mutex here causes hang on FreeBSD when another thread
34 // is suspended)
35 while (!can_work.load())
36 std::this_thread::sleep_for(rtime: std::chrono::milliseconds(50));
37
38 // the mutex guarantees that two writes don't get interspersed
39 {
40 std::lock_guard<std::mutex> lock{print_mutex};
41 std::printf(format: "thread %" PRIx64 " running\n", get_thread_id());
42 }
43
44 // give other threads a fair chance to run
45 for (int i = 0; i < 5; ++i) {
46 std::this_thread::yield();
47 std::this_thread::sleep_for(rtime: std::chrono::milliseconds(200));
48 if (can_exit_now)
49 return;
50 }
51
52 // if we didn't get signaled, terminate the program explicitly.
53 _exit(status: 0);
54}
55
56int main(int argc, char **argv) {
57 int num = atoi(nptr: argv[1]);
58
59 pseudo_barrier_init(barrier, num + 1);
60
61 signal(SIGINT, handler: sigint_handler);
62 signal(SIGUSR1, handler: sigusr1_handler);
63
64 std::vector<std::thread> threads;
65 for (int i = 0; i < num; ++i)
66 threads.emplace_back(args&: thread_func);
67
68 // use the barrier to make sure all threads start before we stop
69 pseudo_barrier_wait(barrier);
70 std::raise(SIGINT);
71
72 // allow the threads to work
73 can_work.store(i: true);
74
75 for (std::thread &thread : threads)
76 thread.join();
77 return 0;
78}
79

source code of lldb/test/API/tools/lldb-server/vCont-threads/main.cpp