system.cpp raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core 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 <bitcoin-build-config.h> // IWYU pragma: keep
   7  
   8  #include <common/system.h>
   9  
  10  #include <util/log.h>
  11  #include <util/string.h>
  12  #include <util/time.h>
  13  
  14  #ifdef WIN32
  15  #include <cassert>
  16  #include <codecvt>
  17  #include <compat/compat.h>
  18  #include <windows.h>
  19  #else
  20  #include <sys/stat.h>
  21  #include <unistd.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  using util::ReplaceAll;
  39  
  40  #ifndef WIN32
  41  std::string ShellEscape(const std::string& arg)
  42  {
  43      std::string escaped = arg;
  44      ReplaceAll(escaped, "'", "'\"'\"'");
  45      return "'" + escaped + "'";
  46  }
  47  #endif
  48  
  49  #if HAVE_SYSTEM
  50  void runCommand(const std::string& strCommand)
  51  {
  52      if (strCommand.empty()) return;
  53  #ifndef WIN32
  54      int nErr = ::system(strCommand.c_str());
  55  #else
  56      int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str());
  57  #endif
  58      if (nErr) {
  59          LogWarning("runCommand error: system(%s) returned %d", strCommand, nErr);
  60      }
  61  }
  62  #endif
  63  
  64  void SetupEnvironment()
  65  {
  66  #ifdef HAVE_MALLOPT_ARENA_MAX
  67      // glibc-specific: On 32-bit systems set the number of arenas to 1.
  68      // By default, since glibc 2.10, the C library will create up to two heap
  69      // arenas per core. This is known to cause excessive virtual address space
  70      // usage in our usage. Work around it by setting the maximum number of
  71      // arenas to 1.
  72      if (sizeof(void*) == 4) {
  73          mallopt(M_ARENA_MAX, 1);
  74      }
  75  #endif
  76      // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
  77      // may be invalid, in which case the "C.UTF-8" locale is used as fallback.
  78  #if !defined(WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
  79      try {
  80          std::locale(""); // Raises a runtime error if current locale is invalid
  81      } catch (const std::runtime_error&) {
  82          setenv("LC_ALL", "C.UTF-8", 1);
  83      }
  84  #elif defined(WIN32)
  85      assert(GetACP() == CP_UTF8);
  86      // Set the default input/output charset is utf-8
  87      SetConsoleCP(CP_UTF8);
  88      SetConsoleOutputCP(CP_UTF8);
  89  #endif
  90  
  91  #ifndef WIN32
  92      constexpr mode_t private_umask = 0077;
  93      umask(private_umask);
  94  #endif
  95  }
  96  
  97  bool SetupNetworking()
  98  {
  99  #ifdef WIN32
 100      // Initialize Windows Sockets
 101      WSADATA wsadata;
 102      int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
 103      if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
 104          return false;
 105  #endif
 106      return true;
 107  }
 108  
 109  int GetNumCores()
 110  {
 111      return std::thread::hardware_concurrency();
 112  }
 113  
 114  std::optional<size_t> GetTotalRAM()
 115  {
 116      [[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }};
 117  #ifdef WIN32
 118      if (MEMORYSTATUSEX m{}; (m.dwLength = sizeof(m), GlobalMemoryStatusEx(&m))) return clamp(m.ullTotalPhys);
 119  #elif defined(__APPLE__) || \
 120        defined(__FreeBSD__) || \
 121        defined(__NetBSD__) || \
 122        defined(__OpenBSD__) || \
 123        defined(__illumos__) || \
 124        defined(__linux__)
 125      if (long p{sysconf(_SC_PHYS_PAGES)}, s{sysconf(_SC_PAGESIZE)}; p > 0 && s > 0) return clamp(1ULL * p * s);
 126  #endif
 127      return std::nullopt;
 128  }
 129  
 130  namespace {
 131      const auto g_startup_time{SteadyClock::now()};
 132  } // namespace
 133  
 134  SteadyClock::duration GetUptime() { return SteadyClock::now() - g_startup_time; }
 135