master
c 137 lines 3.71 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "../libnetdata.h"
4
5 static volatile sig_atomic_t exit_initiated = EXIT_REASON_NONE;
6
7 ENUM_STR_MAP_DEFINE(EXIT_REASON) = {
8 { EXIT_REASON_SIGBUS, "signal-bus-error"},
9 { EXIT_REASON_SIGSEGV, "signal-segmentation-fault"},
10 { EXIT_REASON_SIGFPE, "signal-floating-point-exception"},
11 { EXIT_REASON_SIGILL, "signal-illegal-instruction"},
12 { EXIT_REASON_SIGABRT, "signal-abort"},
13 { EXIT_REASON_SIGSYS, "signal-bad-system-call"},
14 { EXIT_REASON_SIGXCPU, "signal-cpu-time-limit-exceeded"},
15 { EXIT_REASON_SIGXFSZ, "signal-file-size-limit-exceeded"},
16
17 { EXIT_REASON_OUT_OF_MEMORY, "out-of-memory"},
18 { EXIT_REASON_ALREADY_RUNNING, "already-running"},
19
20 { EXIT_REASON_FATAL, "fatal"},
21
22 { EXIT_REASON_API_QUIT, "api-quit"},
23 { EXIT_REASON_CMD_EXIT, "cmd-exit"},
24
25 { EXIT_REASON_SIGQUIT, "signal-quit"},
26 { EXIT_REASON_SIGTERM, "signal-terminate"},
27 { EXIT_REASON_SIGINT, "signal-interrupt"},
28
29 { EXIT_REASON_SERVICE_STOP, "service-stop"},
30
31 { EXIT_REASON_SYSTEM_SHUTDOWN, "system-shutdown"},
32
33 { EXIT_REASON_UPDATE, "update"},
34 { EXIT_REASON_SHUTDOWN_TIMEOUT, "shutdown-timeout"},
35
36 // terminator
37 {0, NULL},
38 };
39
40 BITMAP_STR_DEFINE_FUNCTIONS(EXIT_REASON, EXIT_REASON_NONE, "none");
41
42 #if defined(OS_LINUX)
43 static bool is_system_shutdown_sysv(void) {
44 const char *shutdown_files[] = {
45 "/etc/nologin", // Created during shutdown
46 "/etc/halt", // SysV shutdown indicator
47 "/run/nologin", // Modern systems shutdown indicator
48 NULL
49 };
50
51 for (const char **file = shutdown_files; *file != NULL; file++) {
52 if (access(*file, F_OK) == 0)
53 return true;
54 }
55
56 return false;
57 }
58
59 static bool is_system_shutdown(void) {
60 return is_system_shutdown_sysv();
61 }
62 #endif
63
64 #if defined(OS_FREEBSD)
65 #include <sys/sysctl.h>
66 static bool is_system_shutdown(void) {
67 int state = 0;
68 size_t state_len = sizeof(state);
69
70 if (sysctlbyname("kern.shutdown", &state, &state_len, NULL, 0) == 0)
71 return state != 0;
72
73 return false;
74 }
75 #endif
76
77 #if defined(OS_MACOS)
78 #include <sys/sysctl.h>
79 static bool is_system_shutdown(void) {
80 char buf[1024];
81 size_t len = sizeof(buf);
82
83 if (sysctlbyname("kern.shutdownstate", buf, &len, NULL, 0) == 0)
84 return true;
85
86 if (access("/var/db/.SystemShutdown", F_OK) == 0)
87 return true;
88
89 return false;
90 }
91 #endif
92
93 #if defined(OS_WINDOWS)
94 #include <windows.h>
95 static bool is_system_shutdown(void) {
96 return GetSystemMetrics(SM_SHUTTINGDOWN) != 0;
97 }
98 #endif
99
100 static const char *self_path = NULL;
101 static OS_FILE_METADATA self = { 0 };
102
103 void exit_initiated_init(void) {
104 exit_initiated = EXIT_REASON_NONE;
105
106 freez((char *)self_path);
107 self_path = os_get_process_path();
108 if(self_path)
109 self = os_get_file_metadata(self_path);
110 }
111
112 ALWAYS_INLINE
113 EXIT_REASON exit_initiated_get(void) {
114 return (EXIT_REASON)exit_initiated;
115 }
116
117 void exit_initiated_add(EXIT_REASON reason) {
118 exit_initiated |= (sig_atomic_t)reason;
119 }
120
121 void exit_initiated_set(EXIT_REASON reason) {
122 EXIT_REASON old = exit_initiated_get();
123
124 if(old == EXIT_REASON_NONE && !(reason & EXIT_REASON_SYSTEM_SHUTDOWN) && is_system_shutdown())
125 reason |= EXIT_REASON_SYSTEM_SHUTDOWN;
126
127 if(old == EXIT_REASON_NONE && self_path && OS_FILE_METADATA_OK(self)) {
128 OS_FILE_METADATA self_now = os_get_file_metadata(self_path);
129 if(OS_FILE_METADATA_OK(self_now) && (self_now.modified_time != self.modified_time || self_now.size_bytes != self.size_bytes))
130 reason |= EXIT_REASON_UPDATE;
131 }
132
133 // we combine all of them together
134 // so that if this is called multiple times,
135 // we will have all of them
136 exit_initiated_add(reason);
137 }