pydivert icon indicating copy to clipboard operation
pydivert copied to clipboard

Access Denied error on uninstall

Open ffalcinelli opened this issue 9 years ago • 9 comments
trafficstars

Seems like driver needs to be unregistered before uninstalling the binding.

SYS files are still in use by the Windows Kernel, and trying to remove them results in an Access Denied error (WinError 5).

Successfully uninstalled pydivert-2.0.0
Exception:
Traceback (most recent call last):
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 381, in _rmtree_unsafe
    os.unlink(fullname)
PermissionError: [WinError 5] Accesso negato: 'C:\\Users\\fabio\\AppData\\Local\\Temp\\pip-1vd8riwq-uninstall\\program files (x86)\\python35-32\\lib\\site-packages\\pydivert\\windivert_dll\\windivert64.sys'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\basecommand.py", line 215, in main
    status = self.run(options, args)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\commands\uninstall.py", line 76, in run
    requirement_set.uninstall(auto_confirm=options.yes)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_set.py", line 337, in uninstall
    req.commit_uninstall()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_install.py", line 755, in commit_uninstall
    self.uninstalled.commit()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_uninstall.py", line 142, in commit
    rmtree(self.save_dir)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 49, in wrapped_f
    return Retrying(*dargs, **dkw).call(f, *args, **kw)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 212, in call
    raise attempt.get()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 247, in get
    six.reraise(self.value[0], self.value[1], self.value[2])
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\six.py", line 686, in reraise
    raise value
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 200, in call
    attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\utils\__init__.py", line 102, in rmtree
    onerror=rmtree_errorhandler)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 488, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 383, in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\utils\__init__.py", line 114, in rmtree_errorhandler
    func(path)
PermissionError: [WinError 5] Accesso negato: 'C:\\Users\\fabio\\AppData\\Local\\Temp\\pip-1vd8riwq-uninstall\\program files (x86)\\python35-32\\lib\\site-packages\\pydivert\\windivert_dll\\windivert64.sys'

To delete those files, we must stop the service before using pip

sc stop WinDivert1.1

The WinDivert documentation states that is possible to remove SYS and DLL files and driver will be uninstalled at next reboot, or manually by typing

sc stop WinDivert1.1
sc delete WinDivert1.1

ffalcinelli avatar Oct 18 '16 08:10 ffalcinelli

Since pip has the sole purpose to manage python package, the task to stop service in an uninstall hook is something would never be managed by pip itself, and should not even if an hacky way was available.

So, I think the best solution right now would be to demand this duty to the application or to the developer wanting to uninstall:

  • An application may call Windivert.unregister() before it quits
  • An uninstaller may stop the service before actually uninstalling packages

Maybe this needs to be reported in documentation, or readme

ffalcinelli avatar Oct 18 '16 21:10 ffalcinelli

Yes, that should certainly be part of the PyDivert README/docs. This seems to be an issue in the WinDivert documentation as well:

To uninstall, simply delete the WinDivert.dll, WinDivert32.sys, and WinDivert64.sys files. If already running, the WinDivert driver will be automatically uninstalled during the next machine reboot.

@basil00, can you shed some light on this? :blush:

mhils avatar Oct 23 '16 04:10 mhils

The uninstaller should not stop the driver since other unrelated WinDivert applications may still be using it.

I was unable to reproduce the problem -- I tried deleting the .sys files that were still in use, and it worked as expected (tested with Win7, WinDivert1.2, and admin privileges). That is, the files were gone and the WinDivert service was still running.

basil00 avatar Oct 23 '16 06:10 basil00

Thanks for the super fast reply, @basil00! I can reproduce the issue with WinDivert 1.1 and Windows 10. What system are you on, @ffalcinelli?

mhils avatar Oct 23 '16 08:10 mhils

I'm on Windows 10 too, and maybe it's related to it. This evening I'll be back and I'll try on a Windows 7 virtual machine and let you know.

I've not modified the readme nor documentation since the intended behaviour is as @basil00 stated.

Thank you both :wink:

ffalcinelli avatar Oct 23 '16 10:10 ffalcinelli

Well seems like on a Windows 7 x86 virtual machine it works fine.

What I find really weird:

  • The driver SYS file resides under an uninstall temporary directory and that's of course not the same SYS file the service was actually using... I think, googling a bit, it's an effort to provide a "transactional" uninstall feature for pip so it will move the package in that folder and only after everything is fine pip will actually remove files (but we get the error on W10)
  • If you try to pip install pydivert again, use the the binding and then pip uninstall pydivert for the second time, it's all fine.

ffalcinelli avatar Oct 24 '16 08:10 ffalcinelli

So is this a Win10 issue, or a python+Win10 issue? (I do not have a Win10 test box handy)

basil00 avatar Oct 25 '16 07:10 basil00

This is a Windows 10 issue, unrelated of Python. I cannot delete WinDivert64.sys as long as WinDivert 1.1.8 is running. "access denied" -> sc stop -> "success"

mhils avatar Oct 25 '16 07:10 mhils

In that case it appears that Windows has changed its semantics regarding deleting .sys files that are currently running. This complicates the WinDivert uninstall process, since as mentioned earlier, stopping the WinDivert service is not correct either. Probably "delete-on-reboot" is needed.

basil00 avatar Oct 25 '16 08:10 basil00