Skip to content

Dual process implementation for resolving AccessDenied #304

Closed
@giampaolo

Description

@giampaolo

From g.rodola on July 13, 2012 13:31:17

This is similar to issue 297 but for Windows.

On Windows we use native APIs to extract process information such as CPU times,
memory info etc.
Such APIs systematically fail with an AccessDenied exception for any process
owned by NT AUTHORITY SYSTEM user (system processes, typically) imposing a
severe usability issue for those who want to inspect processes not owned by the
current user (e.g. a task manager like app).
Example:

PID   NAME                 RSS MEM
0     System Idle Process  0
4     System               ACCESS DENIED
172   conhost.exe          3723264
248   svchost.exe          ACCESS DENIED
284   smss.exe             ACCESS DENIED
320   svchost.exe          ACCESS DENIED
328   TSVNCache.exe        7729152
376   csrss.exe            ACCESS DENIED
408   wininit.exe          ACCESS DENIED
424   csrss.exe            ACCESS DENIED
464   winlogon.exe         ACCESS DENIED
512   services.exe         ACCESS DENIED
520   lsass.exe            ACCESS DENIED
528   lsm.exe              ACCESS DENIED
564   python.exe           8675328
572   procexp64.exe        18870272
628   svchost.exe          ACCESS DENIED
688   VBoxService.exe      ACCESS DENIED
728   svchost.exe          ACCESS DENIED
796   explorer.exe         46014464
816   svchost.exe          ACCESS DENIED
856   svchost.exe          ACCESS DENIED
900   svchost.exe          ACCESS DENIED
968   svchost.exe          ACCESS DENIED
1064  dllhost.exe          5214208
1280  cmd.exe              6815744
1296  svchost.exe          ACCESS DENIED
1600  python.exe           5832704
1632  svchost.exe          ACCESS DENIED
1772  taskhost.exe         5554176
1840  dwm.exe              3375104
1852  TortoiseUDiff.exe    4263936
1952  VBoxTray.exe         3039232
2036  procexp.exe          5611520

I realized that a considerable amount of process information which we currently
extract by using documented Windows APIs is also stored in the
SYSTEM_PROCESS_INFORMATION structure, which can be obtained via
NtQuerySystemInformation():
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/System%20Information/Structures/SYSTEM_PROCESS_INFORMATION.html
The peculiarity of NtQuerySystemInformation() is that it succeeds for
basically ALL processes except for PID 0!
On the other hand it is sensibly slower compared to using native APIs.
As such, a natural approach seems to be using the current, native APIs
implementation and fall back on using NtQuerySystemInformation in case of
permission error. Something like:

def get_process_cpu_times():
    try:
        return _psutil_mswindows.get_process_cpu_times()    # native API method
    except AccessDenied:
        return _psutil_mswindows.get_process_cpu_times_2()  # alternative method

Obviously, a robust set of unit tests will have to be written in order to make
sure that the two methods return the exact same value.
Follows a summary of Process methods which can apparently take benefit from
this approach:

 ---------------------------------------------------------------------------
| psutil method          | Win API              | PINFO struct              |
 ---------------------------------------------------------------------------
| create_time           | GetProcessTimes       | CreateTime                |
| nice/priority         | GetPriorityClass      | BasePriority              |
| get_cpu_times()       | GetProcessTimes       | UserTime, KernelTime      |
| get_cpu_percent()     | GetProcessTimes       | UserTime, KernelTime      |
| get_num_handles()     | GetProcessHandleCount | HandleCount               |
| get_memory_info()     | GetProcessMemoryInfo  | WorkingSetSize and others |
| get_ext_memory_info() | GetProcessMemoryInfo  | WorkingSetSize and others |
| get_memory_percent()  | GetProcessMemoryInfo  | WorkingSetSize and others |
| get_threads()         | GetThreadTimes        | Threads*                  |
| get_io_counters()     | GetProcessIoCounters  | *OperationCount           |
 ---------------------------------------------------------------------------

@wj32.64, given the massive amount of code rewriting involved, I'd like to hear
your opinion about this. Does it sounds reasonable and reliable to you?

Original issue: http://code.google.com/p/psutil/issues/detail?id=304

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions