lowleveldesign / process-governor

This application allows you to put various limits on Windows processes.
MIT License
627 stars 62 forks source link

cannot limit multi process at same time #74

Open coldbloodx opened 1 month ago

coldbloodx commented 1 month ago
  1. launch two processes a. testlimit64.exe b. cpustres64.exe

  2. try to limit above new created processes by below command line

    
    C:\Windows\System32>procgov64 -v --cpurate 60 -p 50104,24996
    Process Governor v2.13.24103.12 - sets limits on processes
    Copyright (C) 2023 Sebastian Solnica (lowleveldesign.org)

Max CPU rate: 60%

[procgov] Verbose: 0 : All processes will be assigned to a newly created job (procgov-a4314b0c-8cfd-4fab-9bc2-ffd47b5c22bf). [procgov] Verbose: 0 : Assigning process 50104 to job 'procgov-a4314b0c-8cfd-4fab-9bc2-ffd47b5c22bf' [procgov] Verbose: 0 : Assigning process 24996 to job 'procgov-a4314b0c-8cfd-4fab-9bc2-ffd47b5c22bf' ERROR: 拒绝访问。 (0x80004005) --> should be access denied.



question:
did miss I anything before launching procgov64? 
lowleveldesign commented 1 month ago

Are you using SysInternals from a Microsoft Store package? If so, then they will have already a job assigned (UWP container job) and procgov won't be able to create its own job object. I have plans to support UWP apps, but I haven't yet worked on that.

If you download SysinternalsSuite package and try to run the apps from it, everything should work properly (as with any other non-UWP application):

$cpus = Start-Process -FilePath c:\temp\SysinternalsSuite\CPUSTRES64.EXE -PassThru
$testl = Start-Process -PassThru -FilePath c:\temp\SysinternalsSuite\Testlimit64.EXE -ArgumentList @("-m", "-c", "1000", "-e", "100")
procgov64.exe -v --cpurate 60 -p "$($cpus.Id),$($testl.Id)"

Output:

Process Governor v2.13.24103.12 - sets limits on processes
Copyright (C) 2023 Sebastian Solnica (lowleveldesign.org)

Max CPU rate:                               60%

[procgov] Information: 0 : Setting privilege SeDebugPrivilege for process 9256 failed - 0x514 (probably privilege is not available)
[procgov] Verbose: 0 : All processes will be assigned to a newly created job (procgov-dc3c2f48-4093-408a-b610-b50d9b818c02).
[procgov] Verbose: 0 : Assigning process 2540 to job 'procgov-dc3c2f48-4093-408a-b610-b50d9b818c02'
[procgov] Verbose: 0 : Assigning process 4440 to job 'procgov-dc3c2f48-4093-408a-b610-b50d9b818c02'
Press Ctrl-C to end execution without terminating the process.
lowleveldesign commented 1 month ago

Actually, I will leave it opened and close once I do some more research on UWP apps. Thanks for reporting and let me know if it's actually the problem I described :)

coldbloodx commented 1 month ago

Thanks for reply so quickly :).

Are you using SysInternals from a Microsoft Store package?

Yes, I'm using SysInternals, which downloaded from MS official site.

Following your above steps and launching applications with "windows power shell", the procgov64 can limit the CPU usage for above apps successfully.

I have a question here, AFAIK, I can start up an application(e.g. CPUSTRES64.exe) with below ways: a. double click the application in resource explorer. b. launch the appilcation from "windows terminal" with absolute path. c. launch the application from "windows powershell" with the way you've given me above.

If I launch application with a, I CANNOT add resource limit to the application. But if I launch application from a powershell or terminal command line , the limit could be added to the application successfully.

seems method (a) add the application to a UWP container job automatically, but b/c does not, is my understanding correct?

Is there any way to prevent windows from adding application into UWP container job automatically?

coldbloodx commented 1 month ago

some more interesting findings.

given cpustres64 as example, if I add limit to one of above instance with procgov64, everything goes correctly.

C:\Users\leo.c.wu>procgov64 -v --cpurate 30 --pid 8376
Process Governor v2.13.24103.12 - sets limits on processes
Copyright (C) 2023 Sebastian Solnica (lowleveldesign.org)

Max CPU rate:                               30%

[procgov] Information: 0 : Setting privilege SeDebugPrivilege for process 44268 failed - 0x514 (probably privilege is not available)
Press Ctrl-C to end execution without terminating the process.

image

but if I launched two new instances for the CPUSTRES64.exe by double click the application icon: image

and add limits for the two process, I'll hit the "access denied" error, and cpu limit does not work any more.

C:\Users\leo.c.wu>procgov64 -v --cpurate 40 --pid 47304,9148
Process Governor v2.13.24103.12 - sets limits on processes
Copyright (C) 2023 Sebastian Solnica (lowleveldesign.org)

Max CPU rate:                               40%

[procgov] Information: 0 : Setting privilege SeDebugPrivilege for process 14800 failed - 0x514 (probably privilege is not available)
[procgov] Verbose: 0 : All processes will be assigned to a newly created job (procgov-6ec12ebf-7ffa-4ea4-a482-ec0baf20e2b0).
[procgov] Verbose: 0 : Assigning process 47304 to job 'procgov-6ec12ebf-7ffa-4ea4-a482-ec0baf20e2b0'
[procgov] Verbose: 0 : Assigning process 9148 to job 'procgov-6ec12ebf-7ffa-4ea4-a482-ec0baf20e2b0'
ERROR: 拒绝访问。 (0x80004005)

any ideals about this?

lowleveldesign commented 1 month ago

Thank you for these additional tests. So it looks that the problem is that procgov tries to add two UWP processes in the same job. I suspect it is problematic because UWP processes have already jobs assigned. If you try to run procgov with one PID at a time, it should work. So, in your example, instead of running procgov64 -v --cpurate 40 --pid 47304,9148, you should have run:

procgov64 -v --cpurate 40 --pid 47304
procgov64 -v --cpurate 40 --pid 9148

That will create separate jobs for each of the processes that will be "merged" with the original UWP jobs. As I wrote, I need to do some research on UWP and also improve the errors reported by procgov (the Access Denied is only about the second process - the first one is properly assigned to the job).

If you would like to experiment more, one way to check if a process runs in a job is by using Process Explorer. Run it as admin, find the process you want to check and open the Job tab in its properties, for example:

image

coldbloodx commented 1 month ago

Thank you for replying my questions :).

After reading the manual of windows job object api here: https://learn.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-assignprocesstojobobject I believe I've got the root cause of this issue.

image

see above outlined text:

If the process is already associated with a job, the job specified by hJob must be empty or it must be in the hierarchy of nested jobs to which the process already belongs, and it cannot have UI limits set (SetInformationJobObject with JobObjectBasicUIRestrictions). For more information, see Remarks.

for cpustres64 started by windows shell(explorer), it's already in an UNNAMED job object. image

for cpustres64 started by windows terminal/power shell, it's not in any job object. image

I believe this is the root cause of this behavior :)

I'm trying to limit resource usage e.g. CPU/memory of a set of applications TOGETHER, but not one by one, so I'm trying to create a jobobject and add all processed I want to limit into the job object, but failed as above.

any comments/thoughts on this? :)

lowleveldesign commented 1 month ago

The job hierarchy is not really a "hierarchy". I was able to successfully add a new job to a process that had already a job assigned. The requirement is that the new job must be more "limiting" than the previous one. However, I'm not sure why we get an error when trying to assign multiple processes to the same job.

does not necessarily mean there is no job. You need to run Process Explorer as Admin and when there is no Job tab in the properties, then there is no job for real :) Anyway, for your case, if the applications you want to limit are not store apps, you should be fine with using -p with a list of PIDs.
coldbloodx commented 1 month ago

I'm sure that the "process explorer" is launched with "Admin" permission on above screenshot.

a. for the process start from explorer, in its job tab, we can see the process is put into an unnamed job b. but for process start from cli/power shell, the job drop down shows "access denied"

in my test: (a) could be added into new created job object, but second (a) could not be added into same job object. if the job object is not empty, and there is a process which is already in a unnamed job, the operation will fail.

(b) could be added into new created job, even the job object is not empty.

weird, will continue to try some other case. any findings please let me know thanks in advance :)