system.cpp raw
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-present The Limenka developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <limenka-build-config.h> // IWYU pragma: keep
7
8 #include <common/system.h>
9
10 #include <logging.h>
11 #include <util/string.h>
12 #include <util/subprocess.h>
13 #include <util/time.h>
14
15 #ifndef WIN32
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #else
19 #include <compat/compat.h>
20 #include <codecvt>
21 #include <windows.h>
22 #endif
23
24 #ifdef HAVE_MALLOPT_ARENA_MAX
25 #include <malloc.h>
26 #endif
27
28 #include <algorithm>
29 #include <cstddef>
30 #include <cstdint>
31 #include <cstdlib>
32 #include <locale>
33 #include <optional>
34 #include <stdexcept>
35 #include <string>
36 #include <thread>
37
38 #if HAVE_SYSTEM
39 void runCommand(const std::string& strCommand)
40 {
41 if (strCommand.empty()) return;
42 try {
43 subprocess::Popen p(strCommand, subprocess::close_fds{true});
44 int ret = p.wait();
45 if (ret) {
46 LogWarning("runCommand: %s exited with %d", strCommand, ret);
47 }
48 } catch (const subprocess::CalledProcessError& e) {
49 LogWarning("runCommand: %s failed: %s", strCommand, e.what());
50 } catch (...) {
51 LogWarning("runCommand: %s failed with unknown error", strCommand);
52 }
53 }
54 #endif
55
56 void SetupEnvironment()
57 {
58 #ifdef HAVE_MALLOPT_ARENA_MAX
59 // glibc-specific: On 32-bit systems set the number of arenas to 1.
60 // By default, since glibc 2.10, the C library will create up to two heap
61 // arenas per core. This is known to cause excessive virtual address space
62 // usage in our usage. Work around it by setting the maximum number of
63 // arenas to 1.
64 if (sizeof(void*) == 4) {
65 mallopt(M_ARENA_MAX, 1);
66 }
67 #endif
68 // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
69 // may be invalid, in which case the "C.UTF-8" locale is used as fallback.
70 #if !defined(WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
71 try {
72 std::locale(""); // Raises a runtime error if current locale is invalid
73 } catch (const std::runtime_error&) {
74 setenv("LC_ALL", "C.UTF-8", 1);
75 }
76 #elif defined(WIN32)
77 // Set the default input/output charset is utf-8
78 SetConsoleCP(CP_UTF8);
79 SetConsoleOutputCP(CP_UTF8);
80 #endif
81
82 #ifndef WIN32
83 constexpr mode_t private_umask = 0077;
84 umask(private_umask);
85 #endif
86 }
87
88 bool SetupNetworking()
89 {
90 #ifdef WIN32
91 // Initialize Windows Sockets
92 WSADATA wsadata;
93 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
94 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
95 return false;
96 #endif
97 return true;
98 }
99
100 int GetNumCores()
101 {
102 return std::thread::hardware_concurrency();
103 }
104
105 namespace {
106 const auto g_startup_time{SteadyClock::now()};
107 } // namespace
108
109 SteadyClock::duration GetUptime() { return SteadyClock::now() - g_startup_time; }
110