Add pause-on-process feature

This commit is contained in:
Tony Butler 2021-10-08 21:00:51 -06:00
parent 7627b23212
commit 9385e21b97
10 changed files with 252 additions and 1 deletions

View file

@ -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()

View file

@ -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")

View file

@ -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()

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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();
}

View file

@ -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
}

View file

@ -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;