GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/monitor.h
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 0 9 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 <memory>
15 #include <string>
16
17 #include "util/pipe.h"
18 #include "util/platform.h"
19 #include "util/single_copy.h"
20
21
22 /**
23 * Information for the FUSE module to communicate with the watchdog process
24 * that needs to be preserved through reloads.
25 */
26 class WatchdogState {
27 friend class Watchdog;
28
29 public:
30 ✗ WatchdogState()
31 ✗ : version(0)
32 ✗ , watchdog_write_fd(-1)
33 ✗ , listener_read_fd(-1)
34 ✗ , spawned(false)
35 ✗ , pid(0) { }
36
37 private:
38 unsigned version;
39 int watchdog_write_fd;
40 int listener_read_fd;
41 bool spawned;
42 pid_t pid;
43 };
44
45
46 /**
47 * This class can fork a watchdog process that listens on a pipe and prints a
48 * stackstrace into syslog, when cvmfs fails. The crash dump is also appended
49 * to the crash dump file, if the path is not empty. Singleton.
50 *
51 * The watchdog process if forked on Create and put on hold. Spawn() will start
52 * the supervision and set the crash dump path. It should be called from the
53 * final supervisee pid (after daemon etc.) but preferably before any threads
54 * are started.
55 *
56 * Note: logging should be set up before calling Create()
57 */
58 class Watchdog : SingleCopy {
59 public:
60 /**
61 * Crash cleanup handler signature.
62 */
63 typedef void (*FnOnExit)(const bool crashed);
64
65 static Watchdog *Create(FnOnExit on_exit,
66 bool needs_read_environ,
67 WatchdogState *saved_state = 0,
68 const std::string &oom_score_adj = "");
69 static pid_t GetPid();
70 ~Watchdog();
71 void Spawn(const std::string &crash_dump_path);
72 ✗ void ClearOnExitFn() { on_exit_ = NULL; }
73 ✗ void EnterMaintenanceMode() { maintenance_mode_ = true; }
74 void SaveState(WatchdogState *state);
75
76 /**
77 * Signals that watchdog should not receive. If it does, report and exit.
78 */
79 static int g_suppressed_signals[13];
80 /**
81 * Signals used by crash signal handler. If received, create a stack trace.
82 */
83 static int g_crash_signals[8];
84
85 private:
86 typedef std::map<int, struct sigaction> SigactionMap;
87
88 struct CrashData {
89 int signal;
90 int sys_errno;
91 pid_t pid;
92 };
93
94 struct ControlFlow {
95 enum Flags {
96 kProduceStacktrace = 0,
97 kQuit,
98 kQuitWithExit,
99 kSupervise,
100 kUnknown,
101 };
102 };
103
104 /**
105 * Preallocated memory block to make sure that signal handler don't run into
106 * stack overflows.
107 */
108 static const unsigned kSignalHandlerStacksize = 2 * 1024 * 1024; // 2 MB
109 /**
110 * If the GDB/LLDB method of generating a stack trace fails, fall back to
111 * libc's backtrace with a maximum depth.
112 */
113 static const unsigned kMaxBacktrace = 64;
114
115 static Watchdog *instance_;
116 ✗ static Watchdog *Me() { return instance_; }
117
118 static void *MainWatchdogListener(void *data);
119
120 static void ReportSignalAndContinue(int sig, siginfo_t *siginfo,
121 void *context);
122 static void SendTrace(int sig, siginfo_t *siginfo, void *context);
123
124 Watchdog(FnOnExit on_exit, const std::string &oom_score_adj);
125 void Fork(bool needs_read_environ);
126 void RestoreState(WatchdogState *saved_state);
127 bool WaitForSupervisee();
128 SigactionMap SetSignalHandlers(const SigactionMap &signal_handlers);
129 void Supervise();
130 void LogEmergency(std::string msg);
131 std::string ReportStacktrace();
132 std::string GenerateStackTrace(pid_t pid);
133 std::string ReadUntilGdbPrompt(int fd_pipe);
134
135 bool spawned_;
136 bool maintenance_mode_;
137 std::string crash_dump_path_;
138 std::string exe_path_;
139 std::string oom_score_adj_;
140 pid_t watchdog_pid_;
141 std::unique_ptr<Pipe<kPipeWatchdog> > pipe_watchdog_;
142 /// The supervisee makes sure its watchdog does not die
143 std::unique_ptr<Pipe<kPipeWatchdogSupervisor> > pipe_listener_;
144 /// Send the terminate signal to the listener
145 std::unique_ptr<Pipe<kPipeThreadTerminator> > pipe_terminate_;
146 pthread_t thread_listener_;
147 FnOnExit on_exit_;
148 platform_spinlock lock_handler_;
149 stack_t sighandler_stack_;
150 SigactionMap old_signal_handlers_;
151 };
152
153 #endif // CVMFS_MONITOR_H_
154