giampaolo / psutil

Cross-platform lib for process and system monitoring in Python
BSD 3-Clause "New" or "Revised" License
10.29k stars 1.39k forks source link

Windows: `open_files()` function crashes on inaccessible files. #2203

Open dickermoshe opened 1 year ago

dickermoshe commented 1 year ago

Summary

Description

Using psutil without admin rights will cause many psutil.AccessDenied exceptions to be thrown. I've been using the open_files() without admin rights, everything goes perfectly, until the running program had a file open where the process does not have read rights, or cant access for another reason.

The current logic for the open_files() is to crash if os.stat(path) crashes on one of the opened files. It would make more sense to skip files that crash and at least returns the ones that pass.

In this case, running as admin does not help, the directory fails a os.stat(path) even with admin rights.
The C:\\$Extend\\$Deleted\\ directory always will raise a PermissionError, even when running with admin rights.

BUG: Any Process that has an open file in C:\\$Extend\\$Deleted\\ will crash on a open_files(). FEATURE REQUEST: Add a skip parameter to the open_files() function to skip inaccessible files.

Traceback

Traceback (most recent call last):
  File "C:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\venv\Lib\site-packages\psutil\_pswindows.py", line 688, in wrapper
    return fun(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\venv\Lib\site-packages\psutil\_pswindows.py", line 1005, in open_files
    if isfile_strict(_file):
       ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\venv\Lib\site-packages\psutil\_common.py", line 482, in isfile_strict
    st = os.stat(path)
         ^^^^^^^^^^^^^
PermissionError: [WinError 5] Access is denied: 'C:\\$Extend\\$Deleted\\002E000000034BD31FEA3B5F'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\main.py", line 126, in <module>
    main()
  File "c:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\main.py", line 122, in main
    indesign.run()
  File "c:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\main.py", line 43, in run
    files = self.files()
            ^^^^^^^^^^^^
  File "c:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\main.py", line 84, in files
    files = self.proc.open_files()
            ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\venv\Lib\site-packages\psutil\__init__.py", line 1142, in open_files
    return self._proc.open_files()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Moshe Dicker\Documents\DickerSystems\indesign_saver\venv\Lib\site-packages\psutil\_pswindows.py", line 690, in wrapper
    raise convert_oserror(err, pid=self.pid, name=self._name)
psutil.AccessDenied: (pid=22072)
Benzy-Louis commented 1 year ago

I'd like to have that skip feature too for _pswindows.py#{L994:L1010}, Would something like the following work?

    @wrap_exceptions
    def open_files(self):
        if self.pid in (0, 4):
            return []
        ret = set()
        # Filenames come in in native format like:
        # "\Device\HarddiskVolume1\Windows\systemew\file.txt"
        # Convert the first part in the corresponding drive letter
        # (e.g. "C:\") by using Windows's QueryDosDevice()
        raw_file_names = cext.proc_open_files(self.pid)
        for _file in raw_file_names:
            _file = convert_dos_path(_file)
            try:
                if isfile_strict(_file):
                    if not PY3:
                        _file = py2_strencode(_file)
                    ntuple = _common.popenfile(_file, -1)
                    ret.add(ntuple)
            except PermissionError:
                continue
        return list(ret)