Suspend/Resume all user processes - Is that possible? - c

I have PC's with a lot of applications running at once, i was thinking is it possible to SUSPEND all applications, i want to do that to run periodically one other application that is using a lot the CPU so want it to have all the processor time.
The thing is i want to suspend all applications run my thing that uses the CPU a lot, then when my thingy exit, to resume all applications and all work to be resumed fine....
Any comments are welcome.

It's possible but not recommended at all.
Set the process and thread priority so your application will be given a larger slice of the CPU.
This also means it won't kill the desktop, any network connections, antivirus, start menu, the window manager, etc as your method will.

You could possibly keep a list that you yourself manually generate of programs that are too demanding (say, for (bad) example, Steam.exe, chrome.exe, 90GB-video-game.exe, etc). Basically, you get the entire list of all running processes, search that list for all of the blacklisted names, and NtSuspendProcess/NtResumeProcess (should you need to allow it to run again in the future).
I don't believe suspending all user processes is a good idea. Much of those are weirdly protected and probably should remain running, anyway, and it's an uphill battle with very little to gain.
As mentioned in another answer, you can of course just adjust your processes priority up if you have permission to do so. This sorts the OS-wide process list in favor of your process, so you get CPU time first.
Here's an example of something similar to your original request. I'm writing a program in C++ that needed this exact feature, so I figured I'd help out. This will find Steam.exe or chrome.exe, and suspend the first one it finds for 10 seconds.. then will resume it. This will show as "not responding" on Windows if you try to interact with the window whilst it's suspended. Some applications may not like being suspended, YMMV.
/*Find, suspend, resume Win32 C++
*Written by jimmio92. No rights reserved. Public domain.
*NO WARRANTY! NO LIABILITY! (obviously)
*/
#include <windows.h>
#include <psapi.h>
typedef LONG (NTAPI *NtSuspendProcess)(IN HANDLE ProcessHandle);
typedef LONG (NTAPI *NtResumeProcess)(IN HANDLE ProcessHandle);
NtSuspendProcess dSuspendProcess = nullptr;
NtResumeProcess dResumeProcess = nullptr;
int get_the_pid() {
DWORD procs[4096], bytes;
int out = -1;
if(!EnumProcesses(procs, sizeof(procs), &bytes)) {
return -1;
}
for(size_t i = 0; i < bytes/sizeof(DWORD); ++i) {
TCHAR name[MAX_PATH] = "";
HMODULE mod;
HANDLE p = nullptr;
bool found = false;
p = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procs[i]);
if(p == nullptr)
continue;
DWORD unused_bytes_for_all_modules = 0;
if(EnumProcessModules(p, &mod, sizeof(mod), &unused_bytes_for_all_modules)) {
GetModuleBaseName(p, mod, name, sizeof(name));
//change this to use an array of names or whatever fits your need better
if(strcmp(name, "Steam.exe") == 0 || strcmp(name, "chrome.exe") == 0) {
out = procs[i];
found = true;
}
}
CloseHandle(p);
if(found) break;
}
return out;
}
void suspend_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dSuspendProcess(h);
CloseHandle(h);
}
void resume_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dResumeProcess(h);
CloseHandle(h);
}
void init() {
//load NtSuspendProcess from ntdll.dll
HMODULE ntmod = GetModuleHandle("ntdll");
dSuspendProcess = (NtSuspendProcess)GetProcAddress(ntmod, "NtSuspendProcess");
dResumeProcess = (NtResumeProcess)GetProcAddress(ntmod, "NtResumeProcess");
}
int main() {
init();
int pid = get_the_pid();
if(pid < 0) {
printf("Steam.exe and chrome.exe not found");
}
suspend_process_by_id(pid);
//wait ten seconds for demonstration purposes
Sleep(10000);
resume_process_by_id(pid);
return 0;
}

Related

CreateToolhelp32Snapshot isn't detecting all the modules for a certain process

My code is only outputting a few modules in the process, when there are much more. The procID is correct as i've checked in task manager. I would like it to return every single module in the process.
I'm using a C compiler for this. Is this a problem?
uintptr_t findModuleAddress (char* name, DWORD procID){
MODULEENTRY32 entry;
entry.dwSize = sizeof(MODULEENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procID);
uintptr_t cModuleAddress = 0;
Module32First(snapshot,&entry);
while (Module32Next(snapshot, &entry)){
printf("%s\n",entry.szModule);
if (!strcmp(name,entry.szModule)){
printf("Found module\n");
cModuleAddress = (uintptr_t)entry.modBaseAddr;
break;
}
}
CloseHandle(snapshot);
return cModuleAddress;
}
The output:

proper way to create multiple forked threads

I'm creating a timer function for a bit of embedded code that will allow me to bypass certain GPIO checks while a certain process is running, i.e., when the timer is running in a non-blocking manner.
This seems to run just fine the first 11 times the operations occur, but every time, on the 11th iteration the system will crash. The likely culprit is something in how the timer thread is being handled. My guess is there's some bit of memory cleanup that I'm not handling properly and that's leading to memory leaks of some kind. But I'm really not sure.
I can see through debug tracing that the thread is exiting after each iteration.
Here is the timer code:
#include <time.h>
#include <semaphore.h>
#include <pthread.h>
#include <msp432e4_timer.h>
extern void TaskSleep(uint32_t delay);
static bool timerActive;
static sem_t timerSem;
pthread_t timerThread;
pthread_attr_t attrs;
struct sched_param priParam;
static void *msp432e4_timer(void *argUnused) {
sem_wait(&timerSem);
timerActive = true;
sem_post(&timerSem);
TaskSleep(40);
sem_wait(&timerSem);
timerActive = false;
sem_post(&timerSem);
return (NULL);
}
void initTimer() {
int retc;
pthread_attr_init(&attrs);
priParam.sched_priority = 1;
retc = pthread_attr_setschedparam(&attrs, &priParam);
retc |= pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
retc |= pthread_attr_setstacksize(&attrs, 1024);
if (retc != 0) {
// failed to set attributes
while (1) {}
}
timerActive = false;
if((sem_init(&timerSem, 0, 0)) != 0) {
while(1);
}
sem_post(&timerSem);
}
/*
* return true on starting a new timer
* false implies timer already active
*/
void timerStart() {
int retc;
retc = pthread_create(&timerThread, &attrs, msp432e4_timer, NULL);
if (retc != 0) {
// pthread_create() failed
while (1) {}
}
}
/* return true if timer active */
bool timerCheck() {
bool retval;
sem_wait(&timerSem);
retval = timerActive;
sem_post(&timerSem);
return(retval);
}
The TaskSleep function is a call to a freeRTOS TaskDelay function. It's used in many points throughout the system and has never been an issue.
Hopefully someone can point me in the right direction.
But you didn't really post enough of your code to determine where the problems might be, but I thought this might be worth mentioning:
A general problem is that the sample code you have is open loop wrt thread creation; that is there is nothing to throttle it, and if your implementation has a particularly slow thread exit handling, you could have many zombie threads lying around that haven't died yet.
In typical embedded / real time systems, you want to move resource allocation out of the main loop, since it is often non deterministic. So, more often you would create a timer thread, and park it until it is needed:
void *TimerThread(void *arg) {
while (sem_wait(&request) == 0) {
msp432e4_timer(void *arg);
}
return 0
}
void TimerStart(void) {
sem_post(&request);
}

Measure wall clock time before and after a function

I am measuring wall time through the use of clock_gettime() found in . It works perfectly fine when i use it in main() but not the way i am attempting to use it.
I am familiarizing myself with the linux scheduler and i am measuring performance on different parts.
I want to be able to measure Waiting time which is defined by "the total time a thread spends in the ready queue" (how long until it starts executing the function).
Easily enough i can measure this by setting a clock_gettime() before the thread function and another right inside the function. However the problem i am having is that the time inside the thread function is lower than the one outside, giving us a negative time.
I am running this on my windows pc through ubuntu.
what could the problem be?
code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
perror("Could not create thread");
return 1;
}
}
for(int i = 1;i < threadAmount; i++){
if(pthread_join(tids[i],NULL)!= 0){
perror("Thread could not wait");
return 1;
}
}
and here is my threadfunc:
void *workLoad(void *args)
{
threadData* data = (threadData*) args;
clock_gettime(CLOCK_REALTIME,&data->after);
int loopAmount = data->loopAmount;
int counter = 0;
for(int i = 0; i < loopAmount; i++){
counter++;
}
return NULL;
}
result of time intervall
In the following code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
data seems to be a local variable whose address you pass to the thread. You also copy this variable into thread_array[i-1]. If you then do thread_array[i-1].after - thread_array[i-1].before then that means that the thread updates a wrong variable. You need to pass &thread_array[i-1] to that thread, e.g.:
if(pthread_create(&tids[i],&attr,workLoad,(void*)&thread_array[i-1]) != 0){

Contents in message-queue is changed

I am using uuntu 18.04.1LTS and studying IPC using C. I'm testing Unix i/o using LPC this time, and there's a problem when more than one client connects to the server at the same time.
(when only one client connected, there is no problem.)
sprintf(s1,"./%sA",t);
sprintf(s2, "./%sB", t);
if (MakeDirectory(s1, 0755) == -1) {
return -1;
}
if (MakeDirectory(s2, 0755) == -1) {
return -1;
}
for (i = 0; i < 5; i++)
{
memset(dirName, 0, SIZE);
sprintf(dirName, "%s/%d",s1,i);
usleep(300000);
if (MakeDirectory(dirName, 0755) == -1) {
return -1;
}
}
This code is client's main function. There is no problem at the top, but after running the repeat statement once (when i = 1), MakeDirectory() returns -1 with an error.
(t refers to the pid of the forked process converted into a string.)
int MakeDirectory(char* path, int mode) {
memset(&pRequest, 0x00, LPC_REQUEST_SIZE);
memset(&pResponse, 0x00, LPC_RESPONSE_SIZE);
pRequest.pid = getpid();
pRequest.service = LPC_MAKE_DIRECTORY;
pRequest.numArg = 2;
pRequest.lpcArgs[0].argSize = strlen(path);
strcpy(pRequest.lpcArgs[0].argData, path);
pRequest.lpcArgs[1].argSize = mode;
msgsnd(rqmsqid, &pRequest, LPC_REQUEST_SIZE, 0);
msgrcv(rpmsqid, &pResponse, LPC_RESPONSE_SIZE, getpid(), 0);
int res = pResponse.responseSize;
return res;
}
This is client's MakeDirectory, and
int MakeDirectory(LpcRequest* pRequest) {
memset(&pResponse, 0x00, LPC_RESPONSE_SIZE);
char *path = pRequest->lpcArgs[0].argData;
int mode = pRequest->lpcArgs[1].argSize;
int res = mkdir(path, mode);
pResponse.errorno = 0;
pResponse.pid = pRequest->pid;
printf("%ld\n", pResponse.pid);
pResponse.responseSize = res;
msgsnd(rpmsqid, &pResponse, LPC_RESPONSE_SIZE, 0);
return res;
}
This is a function of the server that runs after checking the pRequest.service when the MakeDirectory function is enabled on the client.
Again, there's nothing wrong with having one client, and if there's more than one. I checked with printf(), but the server passes 0 and the client receives -1. I don't know why this happens.
There's too much missing from your code to know definitively what's happening. I'm placing my bet on either using unallocated memory, or not recognizing a syscall error.
I'm using LTS 16, and there's no definition on my system for LpcRequest or LPC_REQUEST_SIZE, etc. You don't show how they're defined, so we don't know for example if pRequest.lpcArgs[1] exists.
You're also not checking the return code for msgsnd and msgrcv, a sure recipe for endless hours of entertaining debugging.
I suggest you edit your question to include working code, and a shell script that produces the mysterious result. Then someone will be able, if willing, to debug it and explain where you went wrong.
My other suggestion in this area is pretty standard: W. Richard Stevens's books on TCP/IP, specifically Unix Network Programming. If you're studying this stuff, you'll absolutely be glad to have read it.

CreateDesktop() with vista and UAC on (C, windows)

I asked this in CreateDesktop() with Vista UAC (C Windows)
I set a bounty but in trying to vote down the only answer the "accept" was pressed by mistake (i've been awake for more than 48 hs). so I am asking it again.
I'm using CreateDesktop() to create a temporary desktop where an application will run, perform a cleanup action (while remaining out of the way) and terminate. I'm closing that desktop once the application is gone. Everything is fine when using Windows XP and even Vista. The problem arises when you enable the (annoying) UAC.
Everything is OK when you create a desktop, but when you call CreateProcess() to open a program on that desktop it causes the opened application to crash with an exception on User32.dll.
I've been reading a lot about the different desktops and layers on Windows and the restrictions of memory. However, most of the programs I open (as test scenarios) are OK, but a few (like IE, Notepad, Calc and my own application) cause the crash.
Anyone has any idea why this happen on Vista with UAC, or more specifically for those specific programs? and how to fix this?
Anyone has a good solid example on how to create a desktop and open an application there without switching to it under Vista with UAC on?
Code is appreciated.
Thanks
The code used is
SECURITY_ATTRIBUTES sa;
HDESK dOld;
HDESK dNew;
BOOL switchdesk, switchdesk2, closedesk;
int AppPid;
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
//Get handle to current desktop
dOld = OpenDesktopA("default", 0, TRUE, DESKTOP_SWITCHDESKTOP|
DESKTOP_WRITEOBJECTS|
DESKTOP_READOBJECTS|
DESKTOP_ENUMERATE|
DESKTOP_CREATEWINDOW|
DESKTOP_CREATEMENU);
if(!dOld)
{
printf("Failed to get current desktop handle !!\n\n");
return 0;
}
//Make a new desktop
dNew = CreateDesktopA("kaka", 0, 0, 0, DESKTOP_SWITCHDESKTOP|
DESKTOP_WRITEOBJECTS|
DESKTOP_READOBJECTS|
DESKTOP_ENUMERATE|
DESKTOP_CREATEWINDOW|
DESKTOP_CREATEMENU, &sa);
if(!dNew)
{
printf("Failed to create new desktop !!\n\n");
return 0;
}
AppPid = PerformOpenApp(SomeAppPath);
if(AppPid == 0)
{
printf("failed to open app, err = %d\n", GetLastError());
}
else
{
printf("App pid = %d\n", AppPid);
}
closedesk = CloseDesktop(dNew);
if(!closedesk)
{
printf("Failed to close new desktop !!\n\n");
return 0;
}
return 0;
The correct solution is given as a short comment by ChristianWimmer above:
The desktop must have a security descriptor that allows access to lower integrity level like IE has. Otherwise the GUI cannot access the desktop. – ChristianWimmer Jul 22 '10 at 17:00
Since the answer is a little bit hidden and there's no source code example, let me state it clearly here:
If IE runs in protected mode then the browser tabs are created as low integrity processes. The low integrity tab process will fail to initialize if the desktop does not have a low integrity mandatory label.
As a consequence, the main IE process terminates, too. An interesting observation is that if you start IE providing a command line URL from the secure zone, then IE will succeed to start, because protected mode is disabled by default for the secure zone.
I checked the integrity level of the default desktop, and indeed I was able to verify that the default desktop has a low integrity level! So the easiest solution to the problem is to (1) create the new desktop, (2) get the mandatory label from the default desktop, and (3) copy it into the new desktop. For (2) and (3), you can use the following code
PACL pSacl;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD dwResult;
dwResult = GetSecurityInfo(hDefaultDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &pSacl, &pSecurityDescriptor);
if (dwResult == ERROR_SUCCESS) {
if (pSacl != NULL) {
dwResult = SetSecurityInfo(hNewDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl);
if (dwResult != ERROR_SUCCESS)
_tprintf(_T("SetSecurityInfo(hNewDesktop) failed, error = %d"), dwResult);
}
LocalFree(pSecurityDescriptor);
} else {
_tprintf(_T("GetSecurityInfo(hDefaultDesktop) failed, error = %d"), dwResult);
}
#CristianWimmer: Thanks for providing the hint to the correct solution. This saved my a lot of time!!
You appear to have come across a bug in IE as it interacts with UAC. If protected mode is set to on you cannot run IE as an ordinary user in any desktop except the default one. In order to run IE in an alternate desktop you must be running as administrator or have protected mode set to off. This is true for Vista, W2K8 and Win7.
As to the other programs that you cannot run, unfortunately I can't confirm anything. I tried upwards of thirty different programs including notepad, calc, all the office apps, visual studio 2005, 2008 and 2010, MSDN help and a number of others and all worked as expected with the noted exception of IE. Is there something truly unusual about your app that might make it behave in an unexpected manner?
One note - if you attempt to run an application like this that needs elevation (such as regedit, etc.) it will fail in CreateProcess with the last error set to ERROR_ELEVATION_REQUIRED.
For your reference, in case I'm doing something different from you, the code I used is:
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#include <stdio.h>
#include <tchar.h>
#include "windows.h"
HANDLE PerformOpenApp(TCHAR* appPath);
int _tmain(int argc, _TCHAR* argv[])
{
HDESK dNew;
BOOL closedesk;
HANDLE hApp;
//Make a new desktop
dNew = CreateDesktop(_T("kaka"), 0, 0, 0, DESKTOP_SWITCHDESKTOP|
DESKTOP_WRITEOBJECTS|
DESKTOP_READOBJECTS|
DESKTOP_ENUMERATE|
DESKTOP_CREATEWINDOW|
DESKTOP_CREATEMENU, NULL);
if(!dNew)
{
_tprintf(_T("Failed to create new desktop !!\n\n"));
return 0;
}
TCHAR path[MAX_PATH];
_putts(_T("Enter the path of a program to run in the new desktop:\n"));
_getts(path);
while(_tcslen(path) > 0)
{
hApp = PerformOpenApp(path);
if(hApp == 0)
{
_tprintf(_T("Failed to open app, err = %d\n"), GetLastError());
}
else
{
_tprintf(_T("App pid = %d\n"), GetProcessId(hApp));
_putts(_T("Press any key to close the app.\n"));
_gettchar();
TerminateProcess(hApp, 0);
CloseHandle(hApp);
}
_putts(_T("Enter the path of a program to run in the new desktop:\n"));
_getts(path);
}
closedesk = CloseDesktop(dNew);
if(!closedesk)
{
_tprintf(_T("Failed to close new desktop !!\n\n"));
return 0;
}
return 0;
}
HANDLE PerformOpenApp(TCHAR* appPath)
{
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
si.lpDesktop = _T("kaka");
BOOL retVal = CreateProcess(NULL, appPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL,
NULL, &si, &pi);
if (retVal)
{
CloseHandle(pi.hThread);
}
return pi.hProcess;
}

Resources