1
0
Fork 0
forked from len0rd/rockbox

rbutil: add function to suspend/resume processes

Change-Id: I99cfaaa4f853930cea88184496e91589b42859f3
This commit is contained in:
Cástor Muñoz 2016-02-05 00:03:09 +01:00 committed by Franklin Wei
parent 9f7968efdd
commit c353bef3d1
2 changed files with 123 additions and 0 deletions

View file

@ -764,6 +764,128 @@ QMap<QString, QList<int> > Utils::findRunningProcess(QStringList names)
}
/** Suspends/resumes processes
* @param pidlist a list of PIDs to suspend/resume
* @param suspend processes are suspended if true, or resumed when false
* @return a list of PIDs successfully suspended/resumed
*/
QList<int> Utils::suspendProcess(QList<int> pidlist, bool suspend)
{
QList<int> result;
#if defined(Q_OS_WIN32)
// Enable debug privilege
HANDLE hToken = NULL;
LUID seDebugValue;
TOKEN_PRIVILEGES tNext, tPrev;
DWORD sPrev;
if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &seDebugValue)) {
if(OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
memset(&tNext, 0, sizeof(tNext));
tNext.PrivilegeCount = 1;
tNext.Privileges[0].Luid = seDebugValue;
tNext.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken, FALSE, &tNext, sizeof(tNext),
&tPrev, &sPrev) || GetLastError() != 0) {
CloseHandle(hToken);
hToken = NULL;
LOG_ERROR() << "AdjustTokenPrivileges(next) error" << GetLastError();
}
}
else {
LOG_ERROR() << "OpenProcessToken error" << GetLastError();
}
}
else {
LOG_ERROR() << "LookupPrivilegeValue error" << GetLastError();
}
// Suspend/resume threads
for(int i = 0; i < pidlist.size(); i++) {
HANDLE hdl = INVALID_HANDLE_VALUE;
THREADENTRY32 entry;
int n_fails = 0;
hdl = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if(hdl == INVALID_HANDLE_VALUE) {
LOG_ERROR() << "CreateToolhelp32Snapshot error" << GetLastError();
continue;
}
entry.dwSize = sizeof(THREADENTRY32);
if(!Thread32First(hdl, &entry)) {
LOG_ERROR() << "Process32First error" << GetLastError();
CloseHandle(hdl);
continue;
}
do {
if(entry.th32OwnerProcessID != (DWORD)(pidlist[i]))
continue;
HANDLE thr = OpenThread(THREAD_SUSPEND_RESUME,
FALSE, entry.th32ThreadID);
if(!thr) {
LOG_ERROR() << "OpenThread" << entry.th32ThreadID
<< "error" << GetLastError();
n_fails++;
continue;
}
if(suspend) {
// Execution of the specified thread is suspended and
// the thread's suspend count is incremented.
if(SuspendThread(thr) == (DWORD)(-1)) {
LOG_ERROR() << "SuspendThread" << entry.th32ThreadID
<< "error" << GetLastError();
n_fails++;
}
}
else {
// Decrements a thread's suspend count. When the
// suspend count is decremented to zero, the
// execution of the thread is resumed.
if(ResumeThread(thr) == (DWORD)(-1)) {
LOG_ERROR() << "ResumeThread" << entry.th32ThreadID
<< "error" << GetLastError();
n_fails++;
}
}
CloseHandle(thr);
} while(Thread32Next(hdl, &entry));
if (!n_fails)
result.append(pidlist[i]);
CloseHandle(hdl);
}
// Restore previous debug privilege
if (hToken) {
if(!AdjustTokenPrivileges(hToken, FALSE,
&tPrev, sPrev, NULL, NULL) || GetLastError() != 0) {
LOG_ERROR() << "AdjustTokenPrivileges(prev) error" << GetLastError();
}
CloseHandle(hToken);
}
#endif
#if defined(Q_OS_MACX)
int signal = suspend ? SIGSTOP : SIGCONT;
for(int i = 0; i < pidlist.size(); i++) {
pid_t pid = pidlist[i];
if(kill(pid, signal) != 0) {
LOG_ERROR() << "kill signal" << signal
<< "for PID" << pid << "error:" << errno;
}
else {
result.append(pidlist[i]);
}
}
#endif
#if defined(Q_OS_LINUX)
// not implemented for Linux!
#endif
LOG_INFO() << (suspend ? "Suspending" : "Resuming")
<< "PIDs" << pidlist << "result" << result;
return result;
}
/** Eject device from PC.
* Request the OS to eject the player.
* @param device mountpoint of the device

View file

@ -55,6 +55,7 @@ public:
static QString resolveDevicename(QString path);
static QString resolveMountPoint(QString device);
static QMap<QString, QList<int> > findRunningProcess(QStringList names);
static QList<int> suspendProcess(QList<int> pidlist, bool suspend);
static bool ejectDevice(QString device);
};