Add pause-on-process feature
This commit is contained in:
parent
7627b23212
commit
9385e21b97
10 changed files with 252 additions and 1 deletions
|
@ -30,6 +30,7 @@ option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON)
|
|||
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
|
||||
option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF)
|
||||
option(WITH_DMI "Enable DMI/SMBIOS reader" ON)
|
||||
option(WITH_PAUSE_PROCESS "Enable Pause-on-Process feature" ON)
|
||||
|
||||
option(BUILD_STATIC "Build static binary" OFF)
|
||||
option(ARM_TARGET "Force use specific ARM target 8 or 7" 0)
|
||||
|
@ -147,6 +148,9 @@ if (XMRIG_OS_WIN)
|
|||
)
|
||||
|
||||
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
|
||||
if (WITH_PAUSE_PROCESS)
|
||||
list(APPEND EXTRA_LIBS shlwapi)
|
||||
endif()
|
||||
elseif (XMRIG_OS_APPLE)
|
||||
list(APPEND SOURCES_OS
|
||||
src/App_unix.cpp
|
||||
|
@ -171,6 +175,14 @@ else()
|
|||
)
|
||||
|
||||
set(EXTRA_LIBS pthread rt dl)
|
||||
if ((WITH_PAUSE_PROCESS) AND
|
||||
((CMAKE_CXX_COMPILER_ID MATCHES Clang) OR
|
||||
((CMAKE_CXX_COMPILER_ID MATCHES GNU) AND
|
||||
(${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS "9.0.0"))
|
||||
)
|
||||
)
|
||||
list(APPEND EXTRA_LIBS stdc++fs)
|
||||
endif()
|
||||
elseif (XMRIG_OS_FREEBSD)
|
||||
set(EXTRA_LIBS kvm pthread)
|
||||
endif()
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
if (WITH_PAUSE_PROCESS)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
@ -53,7 +56,11 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
|||
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.1.0")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
if (WITH_PAUSE_PROCESS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
|
||||
|
|
|
@ -272,3 +272,10 @@ if (WITH_RANDOMX AND WITH_BENCHMARK)
|
|||
else()
|
||||
remove_definitions(/DXMRIG_FEATURE_BENCHMARK)
|
||||
endif()
|
||||
|
||||
|
||||
if (WITH_PAUSE_PROCESS)
|
||||
add_definitions(/DXMRIG_FEATURE_PAUSE_PROCESS)
|
||||
else()
|
||||
remove_definitions(/DXMRIG_FEATURE_PAUSE_PROCESS)
|
||||
endif()
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
|
||||
#include <cstdint>
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
|
||||
#include "base/tools/String.h"
|
||||
|
@ -47,10 +51,17 @@ public:
|
|||
static void setThreadPriority(int priority);
|
||||
|
||||
static inline bool isUserActive(uint64_t ms) { return idleTime() < ms; }
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
static inline bool isProcessActive(std::vector<std::string> search) { return checkProcesses(search); }
|
||||
#endif
|
||||
static inline const String &userAgent() { return m_userAgent; }
|
||||
|
||||
static bool isOnBatteryPower();
|
||||
static uint64_t idleTime();
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
static bool checkProcesses(std::vector<std::string>&);
|
||||
std::vector<std::string> processList;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static char *createUserAgent();
|
||||
|
|
|
@ -109,6 +109,15 @@ bool xmrig::Platform::isOnBatteryPower()
|
|||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
bool xmrig::Platform::checkProcesses(std::vector<std::string>& processList)
|
||||
{
|
||||
// not yet implemented
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint64_t xmrig::Platform::idleTime()
|
||||
{
|
||||
uint64_t idle_time = 0;
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
|
||||
#include "base/kernel/Platform.h"
|
||||
|
@ -161,6 +167,65 @@ bool xmrig::Platform::isOnBatteryPower()
|
|||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
struct ci_char_traits : public std::char_traits<char> {
|
||||
static bool eq(char c1, char c2) { return std::tolower(c1) == std::tolower(c2); }
|
||||
static bool ne(char c1, char c2) { return std::tolower(c1) != std::tolower(c2); }
|
||||
static bool lt(char c1, char c2) { return std::tolower(c1) < std::tolower(c2); }
|
||||
static int compare(const char* s1, const char* s2, size_t n) {
|
||||
while( n-- != 0 ) {
|
||||
if( std::tolower(*s1) < std::tolower(*s2) ) return -1;
|
||||
if( std::tolower(*s1) > std::tolower(*s2) ) return 1;
|
||||
++s1; ++s2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static const char* find(const char* s, int n, char a) {
|
||||
while( n-- > 0 && std::tolower(*s) != std::tolower(a) ) {
|
||||
++s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
bool IsNumeric(const std::string& s)
|
||||
{
|
||||
return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
|
||||
}
|
||||
|
||||
bool xmrig::Platform::checkProcesses(std::vector<std::string>& processList)
|
||||
{
|
||||
const std::filesystem::path proc{"/proc/"};
|
||||
for(auto const& dirEnt: std::filesystem::directory_iterator{proc})
|
||||
{
|
||||
if (dirEnt.is_directory() && IsNumeric(dirEnt.path().stem().string()))
|
||||
{
|
||||
std::string procFile = dirEnt.path().string() + "/cmdline";
|
||||
std::ifstream myfile (procFile);
|
||||
if (myfile.is_open())
|
||||
{
|
||||
std::string cmdLine;
|
||||
std::getline(myfile, cmdLine);
|
||||
myfile.close();
|
||||
std::basic_string_view<std::string::value_type, ci_char_traits> cmdLineCI{ cmdLine.c_str() };
|
||||
if (!cmdLine.empty())
|
||||
{
|
||||
for (auto const& processName : processList)
|
||||
{
|
||||
if (cmdLineCI.find(processName.c_str()) != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint64_t xmrig::Platform::idleTime()
|
||||
{
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
|
|
|
@ -22,6 +22,14 @@
|
|||
#include <windows.h>
|
||||
#include <uv.h>
|
||||
#include <limits>
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
#include <tchar.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
|
||||
#include "base/kernel/Platform.h"
|
||||
|
@ -175,3 +183,60 @@ uint64_t xmrig::Platform::idleTime()
|
|||
|
||||
return static_cast<uint64_t>(GetTickCount() - info.dwTime);
|
||||
}
|
||||
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
std::wstring s2ws(const std::string& s)
|
||||
{
|
||||
int len;
|
||||
int slength = (int)s.length() + 1;
|
||||
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
||||
std::wstring buf;
|
||||
buf.resize(len);
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, const_cast<WCHAR*>(buf.c_str()), len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool xmrig::Platform::checkProcesses(std::vector<std::string>& processList)
|
||||
{
|
||||
DWORD aProcesses[1024], cbNeeded;
|
||||
unsigned int i;
|
||||
DWORD dwProcessNameLen;
|
||||
|
||||
if (EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
|
||||
{
|
||||
for (i = 0; i < cbNeeded / sizeof(DWORD); i++)
|
||||
{
|
||||
if (aProcesses[i] != 0)
|
||||
{
|
||||
std::unique_ptr<WCHAR[]> wszProcessName(new WCHAR[MAX_PATH]);
|
||||
std::unique_ptr<WCHAR[]> wszSearchName(new WCHAR[MAX_PATH]);
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
|
||||
if (NULL != hProcess)
|
||||
{
|
||||
HMODULE hMod;
|
||||
DWORD cbNeeded;
|
||||
if (EnumProcessModulesEx(hProcess, &hMod, sizeof(hMod), &cbNeeded, LIST_MODULES_ALL))
|
||||
{
|
||||
dwProcessNameLen = MAX_PATH;
|
||||
if (QueryFullProcessImageName(hProcess, 0, wszProcessName.get(), &dwProcessNameLen))
|
||||
{
|
||||
for (auto const& searchName : processList)
|
||||
{
|
||||
std::wstring wrapper = s2ws(searchName);
|
||||
wcsncpy_s(wszSearchName.get(), MAX_PATH / sizeof(WCHAR), wrapper.c_str(), wrapper.length());
|
||||
if (NULL != StrStrI(wszProcessName.get(), wszSearchName.get()))
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -339,6 +339,9 @@ public:
|
|||
bool active = false;
|
||||
bool battery_power = false;
|
||||
bool user_active = false;
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
bool process_active = false;
|
||||
# endif
|
||||
bool enabled = true;
|
||||
int32_t auto_pause = 0;
|
||||
bool reset = true;
|
||||
|
@ -640,6 +643,12 @@ void xmrig::Miner::onTimer(const Timer *)
|
|||
autoPause(d_ptr->user_active, Platform::isUserActive(config->idleTime()), YELLOW_BOLD("user active"), GREEN_BOLD("user inactive"));
|
||||
}
|
||||
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
if (config->isPauseOnProcess()) {
|
||||
autoPause(d_ptr->process_active, Platform::isProcessActive(config->processList()), YELLOW_BOLD("process active"), GREEN_BOLD("process inactive"));
|
||||
}
|
||||
# endif
|
||||
|
||||
if (stopMiner) {
|
||||
stop();
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ constexpr static uint32_t kIdleTime = 60U;
|
|||
|
||||
const char *Config::kPauseOnBattery = "pause-on-battery";
|
||||
const char *Config::kPauseOnActive = "pause-on-active";
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
const char *Config::kPauseOnProcess = "pause-on-process";
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_OPENCL
|
||||
|
@ -79,6 +82,9 @@ public:
|
|||
bool pauseOnBattery = false;
|
||||
CpuConfig cpu;
|
||||
uint32_t idleTime = 0;
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
std::vector<std::string> processList;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
RxConfig rx;
|
||||
|
@ -109,6 +115,21 @@ public:
|
|||
idleTime = value.GetUint();
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
void setPauseProcesses(const rapidjson::Value &value)
|
||||
{
|
||||
processList.clear();
|
||||
if (value.IsArray()) {
|
||||
for (const rapidjson::Value &item : value.GetArray()) {
|
||||
if (!item.IsString()) {
|
||||
continue;
|
||||
}
|
||||
processList.push_back(item.GetString());
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
};
|
||||
|
||||
} // namespace xmrig
|
||||
|
@ -144,6 +165,34 @@ uint32_t xmrig::Config::idleTime() const
|
|||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
std::vector<std::string> xmrig::Config::processList() const
|
||||
{
|
||||
return d_ptr->processList;
|
||||
}
|
||||
|
||||
rapidjson::Value xmrig::Config::getPauseProcesses(rapidjson::Document &doc) const
|
||||
{
|
||||
rapidjson::Value out;
|
||||
|
||||
if (!d_ptr->processList.empty()) {
|
||||
auto &allocator = doc.GetAllocator();
|
||||
|
||||
out.SetArray();
|
||||
|
||||
for (const auto& process: d_ptr->processList) {
|
||||
rapidjson::Value value;
|
||||
value.SetString(process.c_str(), allocator);
|
||||
out.PushBack(value, allocator);
|
||||
}
|
||||
}
|
||||
else out.SetBool(false);
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_OPENCL
|
||||
const xmrig::OclConfig &xmrig::Config::cl() const
|
||||
{
|
||||
|
@ -214,6 +263,9 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
|
|||
|
||||
d_ptr->pauseOnBattery = reader.getBool(kPauseOnBattery, d_ptr->pauseOnBattery);
|
||||
d_ptr->setIdleTime(reader.getValue(kPauseOnActive));
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
d_ptr->setPauseProcesses(reader.getArray(kPauseOnProcess));
|
||||
# endif
|
||||
|
||||
d_ptr->cpu.read(reader.getValue(CpuConfig::kField));
|
||||
|
||||
|
@ -305,4 +357,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
|
|||
doc.AddMember(StringRef(kWatch), m_watch, allocator);
|
||||
doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator);
|
||||
doc.AddMember(StringRef(kPauseOnActive), (d_ptr->idleTime == 0U || d_ptr->idleTime == kIdleTime) ? Value(isPauseOnActive()) : Value(d_ptr->idleTime), allocator);
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
doc.AddMember(StringRef(kPauseOnProcess), getPauseProcesses(doc), allocator);
|
||||
# endif
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
|
||||
#include <cstdint>
|
||||
#ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
|
||||
#include "3rdparty/rapidjson/fwd.h"
|
||||
|
@ -46,6 +49,9 @@ public:
|
|||
|
||||
static const char *kPauseOnBattery;
|
||||
static const char *kPauseOnActive;
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
static const char *kPauseOnProcess;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_FEATURE_OPENCL
|
||||
static const char *kOcl;
|
||||
|
@ -67,10 +73,15 @@ public:
|
|||
~Config() override;
|
||||
|
||||
inline bool isPauseOnActive() const { return idleTime() > 0; }
|
||||
# ifdef XMRIG_FEATURE_PAUSE_PROCESS
|
||||
inline bool isPauseOnProcess() const { return !processList().empty(); }
|
||||
# endif
|
||||
|
||||
bool isPauseOnBattery() const;
|
||||
const CpuConfig &cpu() const;
|
||||
uint32_t idleTime() const;
|
||||
std::vector<std::string> processList() const;
|
||||
rapidjson::Value getPauseProcesses(rapidjson::Document &doc) const;
|
||||
|
||||
# ifdef XMRIG_FEATURE_OPENCL
|
||||
const OclConfig &cl() const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue