GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/monitor.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 1 0.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_MONITOR_H_
6 #define CVMFS_MONITOR_H_
7
8 #include <pthread.h>
9 #include <signal.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include <map>
14 #include <string>
15
16 #include "util/pipe.h"
17 #include "util/platform.h"
18 #include "util/pointer.h"
19 #include "util/single_copy.h"
20
21 /**
22 * This class can fork a watchdog process that listens on a pipe and prints a
23 * stackstrace into syslog, when cvmfs fails. The crash dump is also appended
24 * to the crash dump file, if the path is not empty. Singleton.
25 *
26 * The watchdog process if forked on Create and put on hold. Spawn() will start
27 * the supervision and set the crash dump path. It should be called from the
28 * final supervisee pid (after daemon etc.) but preferably before any threads
29 * are started.
30 *
31 * Note: logging should be set up before calling Create()
32 */
33 class Watchdog : SingleCopy {
34 public:
35 /**
36 * Crash cleanup handler signature.
37 */
38 typedef void (*FnOnCrash)(void);
39
40 static Watchdog *Create(FnOnCrash on_crash);
41 static pid_t GetPid();
42 ~Watchdog();
43 void Spawn(const std::string &crash_dump_path);
44
45 /**
46 * Signals that watchdog should not receive. If it does, report and exit.
47 */
48 static int g_suppressed_signals[13];
49 /**
50 * Signals used by crash signal handler. If received, create a stack trace.
51 */
52 static int g_crash_signals[8];
53
54 private:
55 typedef std::map<int, struct sigaction> SigactionMap;
56
57 struct CrashData {
58 int signal;
59 int sys_errno;
60 pid_t pid;
61 };
62
63 struct ControlFlow {
64 enum Flags {
65 kProduceStacktrace = 0,
66 kQuit,
67 kSupervise,
68 kUnknown,
69 };
70 };
71
72 /**
73 * Preallocated memory block to make sure that signal handler don't run into
74 * stack overflows.
75 */
76 static const unsigned kSignalHandlerStacksize = 2 * 1024 * 1024; // 2 MB
77 /**
78 * If the GDB/LLDB method of generating a stack trace fails, fall back to
79 * libc's backtrace with a maximum depth.
80 */
81 static const unsigned kMaxBacktrace = 64;
82
83 static Watchdog *instance_;
84 static Watchdog *Me() { return instance_; }
85
86 static void *MainWatchdogListener(void *data);
87
88 static void ReportSignalAndTerminate(int sig, siginfo_t *siginfo,
89 void *context);
90 static void SendTrace(int sig, siginfo_t *siginfo, void *context);
91
92 explicit Watchdog(FnOnCrash on_crash);
93 void Fork();
94 bool WaitForSupervisee();
95 SigactionMap SetSignalHandlers(const SigactionMap &signal_handlers);
96 void Supervise();
97 void LogEmergency(std::string msg);
98 std::string ReportStacktrace();
99 std::string GenerateStackTrace(pid_t pid);
100 std::string ReadUntilGdbPrompt(int fd_pipe);
101
102 bool spawned_;
103 std::string crash_dump_path_;
104 std::string exe_path_;
105 pid_t watchdog_pid_;
106 UniquePtr<Pipe<kPipeWatchdog> > pipe_watchdog_;
107 /// The supervisee makes sure its watchdog does not die
108 UniquePtr<Pipe<kPipeWatchdogSupervisor> > pipe_listener_;
109 /// Send the terminate signal to the listener
110 UniquePtr<Pipe<kPipeThreadTerminator> > pipe_terminate_;
111 pthread_t thread_listener_;
112 FnOnCrash on_crash_;
113 platform_spinlock lock_handler_;
114 stack_t sighandler_stack_;
115 SigactionMap old_signal_handlers_;
116 };
117
118 #endif // CVMFS_MONITOR_H_
119