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