forked from len0rd/rockbox
rbutil: add function to suspend/resume processes
Change-Id: I99cfaaa4f853930cea88184496e91589b42859f3
This commit is contained in:
parent
9f7968efdd
commit
c353bef3d1
2 changed files with 123 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue