master
h 187 lines 4.71 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 common.h
8
9 Abstract:
10
11 This file contains common/shared information.
12
13 --*/
14
15 #pragma once
16
17 #ifndef TEMP_FAILURE_RETRY
18 #define TEMP_FAILURE_RETRY(expression) \
19 (__extension__({ \
20 long int __result; \
21 do \
22 __result = (long int)(expression); \
23 while (__result == -1L && errno == EINTR); \
24 __result; \
25 }))
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <stddef.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <sched.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <sys/syscall.h>
39 #include <sys/reboot.h>
40 #include <sys/un.h>
41 #include <dirent.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <signal.h>
45 #include <poll.h>
46 #include <utility>
47 #include <format>
48 #include <type_traits>
49 #include <new>
50 #include <thread>
51 #include <vector>
52 #include <gsl/gsl>
53 #include <gslhelpers.h>
54 #include <lxwil.h>
55 #include <cstdarg>
56 #include "lxinitshared.h"
57 #include "defs.h"
58
59 #define ETC_FOLDER "/etc/"
60 #define NAME_ENV "NAME"
61 #define INIT_PATH "/sbin/init"
62 #define INTEROP_TIMEOUT_MS (INTEROP_TIMEOUT_SEC * 1000)
63 #define SESSION_LEADER_ACCEPT_TIMEOUT_MS (30 * 1000)
64 #define INTEROP_TIMEOUT_SEC (10)
65 #define RUN_FOLDER "/run"
66 #define WSL_SAFE_MODE_WARNING "SAFE MODE ENABLED"
67 #define CONFIG_FILE ETC_FOLDER "wsl.conf"
68
69 extern thread_local std::string g_threadName;
70 extern int g_LogFd;
71 extern int g_TelemetryFd;
72 extern struct sigaction g_SavedSignalActions[_NSIG];
73
74 //
75 // N.B. The clone syscall is used directly instead of the libc wrapper, because
76 // it allows execution to continue at the point of the call with a
77 // copy-on-write stack.
78 //
79 // The clone syscall argument are architecture-specific:
80 // x86, arm, arm64: clone(flags, stack, ptid, tls, ctid)
81 // amd64: clone(flags, stack, ptid, ctid, tls)
82 //
83
84 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__)
85 #define CLONE(_flags) syscall(SYS_clone, (_flags), NULL, NULL, NULL, NULL);
86 #elif defined(__x86_64__)
87 #define CLONE(_flags) syscall(SYS_clone, (_flags), NULL, NULL, NULL, NULL);
88 #else
89 #error CLONE function signature is architecture-specific.
90 #endif
91
92 #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0]))
93
94 #define CLOSE(_fd) \
95 { \
96 if (_fd != -1 && close(_fd) < 0) \
97 { \
98 FATAL_ERROR("close({}) {}", _fd, errno); \
99 } \
100 }
101
102 template <typename T>
103 T&& NormalizeLogArgument(T&& Argument)
104 {
105 using ArgumentType = std::remove_cv_t<std::remove_reference_t<T>>;
106
107 if constexpr (std::is_same_v<ArgumentType, char*> || std::is_same_v<ArgumentType, const char*>)
108 {
109 if (Argument == nullptr)
110 {
111 static char NullString[] = "<null>";
112 static ArgumentType NullArgument = NullString;
113 return static_cast<T&&>(NullArgument);
114 }
115 }
116
117 return std::forward<T>(Argument);
118 }
119
120 template <typename... Args>
121 auto LogImpl(int fd, const std::format_string<Args...>& format, Args&&... args)
122 {
123 auto logline = std::format(format, NormalizeLogArgument(std::forward<Args>(args))...);
124 if (logline.empty())
125 {
126 return;
127 }
128
129 if (logline.back() != '\n')
130 {
131 logline.push_back('\n');
132 }
133
134 write(fd, logline.c_str(), logline.size());
135 }
136
137 #define LOG_ERROR(str, ...) \
138 { \
139 LogImpl(g_LogFd, "<3>WSL ({} - {}) ERROR: {}:{}: " str "\n", getpid(), g_threadName.c_str(), __FUNCTION__, __LINE__, ##__VA_ARGS__); \
140 }
141
142 #define LOG_INFO(str, ...) \
143 { \
144 LogImpl(g_LogFd, "<6>WSL ({} - {}): " str "\n", getpid(), g_threadName.c_str(), ##__VA_ARGS__); \
145 }
146
147 #define LOG_WARNING(str, ...) \
148 { \
149 LogImpl(g_LogFd, "<4>WSL ({} - {}) WARNING: " str "\n", getpid(), g_threadName.c_str(), ##__VA_ARGS__); \
150 }
151
152 #define FATAL_ERROR_EX(status, str, ...) \
153 { \
154 LOG_ERROR(str, ##__VA_ARGS__); \
155 _exit(status); \
156 }
157
158 #define GNS_LOG_INFO(str, ...) \
159 { \
160 if (g_TelemetryFd != -1) \
161 { \
162 LogImpl(g_TelemetryFd, "{}: {} - " str "\n", g_threadName.c_str(), __FUNCTION__, ##__VA_ARGS__); \
163 } \
164 }
165
166 #define GNS_LOG_ERROR(str, ...) \
167 { \
168 if (g_TelemetryFd != -1) \
169 { \
170 LogImpl(g_TelemetryFd, "{}: {} - ERROR: " str "\n", g_threadName.c_str(), __FUNCTION__, ##__VA_ARGS__); \
171 } \
172 else \
173 { \
174 LOG_ERROR(str, ##__VA_ARGS__); \
175 } \
176 }
177
178 #define FATAL_ERROR(str, ...) FATAL_ERROR_EX(1, str, ##__VA_ARGS__)
179
180 // Some of these files need the LOG_* macros.
181 #include "retryshared.h"
182 #include "socketshared.h"
183 #include "stringshared.h"
184
185 int InitializeLogging(bool SetStderr, wil::LogFunction* ExceptionCallback = nullptr) noexcept;
186
187 void LogException(const char* Message, const char* Description) noexcept;