diff options
author | Cástor Muñoz <cmvidal@gmail.com> | 2016-02-05 00:03:09 +0100 |
---|---|---|
committer | Franklin Wei <franklin@rockbox.org> | 2019-10-28 00:09:35 -0400 |
commit | c353bef3d1902229be40118ce6b52770e5346787 (patch) | |
tree | cf2332df652aaf071e2402b1ecc2557aa859c119 /rbutil/rbutilqt/base/utils.cpp | |
parent | 9f7968efdd31e0b3753c698676fbbd92339320d9 (diff) | |
download | rockbox-c353bef3d1902229be40118ce6b52770e5346787.tar.gz rockbox-c353bef3d1902229be40118ce6b52770e5346787.zip |
rbutil: add function to suspend/resume processes
Change-Id: I99cfaaa4f853930cea88184496e91589b42859f3
Diffstat (limited to 'rbutil/rbutilqt/base/utils.cpp')
-rw-r--r-- | rbutil/rbutilqt/base/utils.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp index f58d8c34e3..099f9c7742 100644 --- a/rbutil/rbutilqt/base/utils.cpp +++ b/rbutil/rbutilqt/base/utils.cpp | |||
@@ -764,6 +764,128 @@ QMap<QString, QList<int> > Utils::findRunningProcess(QStringList names) | |||
764 | } | 764 | } |
765 | 765 | ||
766 | 766 | ||
767 | /** Suspends/resumes processes | ||
768 | * @param pidlist a list of PIDs to suspend/resume | ||
769 | * @param suspend processes are suspended if true, or resumed when false | ||
770 | * @return a list of PIDs successfully suspended/resumed | ||
771 | */ | ||
772 | QList<int> Utils::suspendProcess(QList<int> pidlist, bool suspend) | ||
773 | { | ||
774 | QList<int> result; | ||
775 | #if defined(Q_OS_WIN32) | ||
776 | // Enable debug privilege | ||
777 | HANDLE hToken = NULL; | ||
778 | LUID seDebugValue; | ||
779 | TOKEN_PRIVILEGES tNext, tPrev; | ||
780 | DWORD sPrev; | ||
781 | if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &seDebugValue)) { | ||
782 | if(OpenProcessToken(GetCurrentProcess(), | ||
783 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { | ||
784 | memset(&tNext, 0, sizeof(tNext)); | ||
785 | tNext.PrivilegeCount = 1; | ||
786 | tNext.Privileges[0].Luid = seDebugValue; | ||
787 | tNext.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; | ||
788 | if(!AdjustTokenPrivileges(hToken, FALSE, &tNext, sizeof(tNext), | ||
789 | &tPrev, &sPrev) || GetLastError() != 0) { | ||
790 | CloseHandle(hToken); | ||
791 | hToken = NULL; | ||
792 | LOG_ERROR() << "AdjustTokenPrivileges(next) error" << GetLastError(); | ||
793 | } | ||
794 | } | ||
795 | else { | ||
796 | LOG_ERROR() << "OpenProcessToken error" << GetLastError(); | ||
797 | } | ||
798 | } | ||
799 | else { | ||
800 | LOG_ERROR() << "LookupPrivilegeValue error" << GetLastError(); | ||
801 | } | ||
802 | |||
803 | // Suspend/resume threads | ||
804 | for(int i = 0; i < pidlist.size(); i++) { | ||
805 | HANDLE hdl = INVALID_HANDLE_VALUE; | ||
806 | THREADENTRY32 entry; | ||
807 | int n_fails = 0; | ||
808 | |||
809 | hdl = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | ||
810 | if(hdl == INVALID_HANDLE_VALUE) { | ||
811 | LOG_ERROR() << "CreateToolhelp32Snapshot error" << GetLastError(); | ||
812 | continue; | ||
813 | } | ||
814 | entry.dwSize = sizeof(THREADENTRY32); | ||
815 | if(!Thread32First(hdl, &entry)) { | ||
816 | LOG_ERROR() << "Process32First error" << GetLastError(); | ||
817 | CloseHandle(hdl); | ||
818 | continue; | ||
819 | } | ||
820 | |||
821 | do { | ||
822 | if(entry.th32OwnerProcessID != (DWORD)(pidlist[i])) | ||
823 | continue; | ||
824 | HANDLE thr = OpenThread(THREAD_SUSPEND_RESUME, | ||
825 | FALSE, entry.th32ThreadID); | ||
826 | if(!thr) { | ||
827 | LOG_ERROR() << "OpenThread" << entry.th32ThreadID | ||
828 | << "error" << GetLastError(); | ||
829 | n_fails++; | ||
830 | continue; | ||
831 | } | ||
832 | if(suspend) { | ||
833 | // Execution of the specified thread is suspended and | ||
834 | // the thread's suspend count is incremented. | ||
835 | if(SuspendThread(thr) == (DWORD)(-1)) { | ||
836 | LOG_ERROR() << "SuspendThread" << entry.th32ThreadID | ||
837 | << "error" << GetLastError(); | ||
838 | n_fails++; | ||
839 | } | ||
840 | } | ||
841 | else { | ||
842 | // Decrements a thread's suspend count. When the | ||
843 | // suspend count is decremented to zero, the | ||
844 | // execution of the thread is resumed. | ||
845 | if(ResumeThread(thr) == (DWORD)(-1)) { | ||
846 | LOG_ERROR() << "ResumeThread" << entry.th32ThreadID | ||
847 | << "error" << GetLastError(); | ||
848 | n_fails++; | ||
849 | } | ||
850 | } | ||
851 | CloseHandle(thr); | ||
852 | } while(Thread32Next(hdl, &entry)); | ||
853 | if (!n_fails) | ||
854 | result.append(pidlist[i]); | ||
855 | CloseHandle(hdl); | ||
856 | } | ||
857 | |||
858 | // Restore previous debug privilege | ||
859 | if (hToken) { | ||
860 | if(!AdjustTokenPrivileges(hToken, FALSE, | ||
861 | &tPrev, sPrev, NULL, NULL) || GetLastError() != 0) { | ||
862 | LOG_ERROR() << "AdjustTokenPrivileges(prev) error" << GetLastError(); | ||
863 | } | ||
864 | CloseHandle(hToken); | ||
865 | } | ||
866 | #endif | ||
867 | #if defined(Q_OS_MACX) | ||
868 | int signal = suspend ? SIGSTOP : SIGCONT; | ||
869 | for(int i = 0; i < pidlist.size(); i++) { | ||
870 | pid_t pid = pidlist[i]; | ||
871 | if(kill(pid, signal) != 0) { | ||
872 | LOG_ERROR() << "kill signal" << signal | ||
873 | << "for PID" << pid << "error:" << errno; | ||
874 | } | ||
875 | else { | ||
876 | result.append(pidlist[i]); | ||
877 | } | ||
878 | } | ||
879 | #endif | ||
880 | #if defined(Q_OS_LINUX) | ||
881 | // not implemented for Linux! | ||
882 | #endif | ||
883 | LOG_INFO() << (suspend ? "Suspending" : "Resuming") | ||
884 | << "PIDs" << pidlist << "result" << result; | ||
885 | return result; | ||
886 | } | ||
887 | |||
888 | |||
767 | /** Eject device from PC. | 889 | /** Eject device from PC. |
768 | * Request the OS to eject the player. | 890 | * Request the OS to eject the player. |
769 | * @param device mountpoint of the device | 891 | * @param device mountpoint of the device |