I'm writing an updater for an application. I need to remove the old files as they're running. This works fine until I hit dll files that I'm using. For various reasons I have to bundle the _ssl compiled library with my distribution.
I'm firstly freeing the library, which for whatever reason requires two calls to actually remove the handle (I'm assuming there is refcounting going on somewhere). After this, I try and remove the file. This results in Python dying with a 0xC0000005 which is apparently a very broad exit code.
import ssl
import ctypes
import _ctypes
print "Unloading SSL Module"
ssl_filename = ssl._ssl.__file__
dll = ctypes.CDLL(ssl_filename)
if ssl_filename.endswith("pyd"):
_ctypes.FreeLibrary(dll._handle)
_ctypes.FreeLibrary(dll._handle)
else:
_ctypes.dlclose(dll._handle)
_ctypes.dlclose(dll._handle)
print "Deleting current version..."
os.remove(ssl_filename)
print "Success"
Upon execution I get the following:
Unloading SSL Module
__builtin__ C:\path\to\_ssl.pyd 0 Deleting current version...
Process finished with exit code -1073741819 (0xC0000005)
What I'm expecting is for the code to remove the file and continue as normal.
Moving in-use DLLs instead of deleting them You're running into a fundamental Windows limitation - you simply can't delete DLL files that are currently loaded in memory by the running process.
Even though you're trying to free the library with _ctypes.FreeLibrary(), the Python interpreter itself may still have dependencies on this library (especially _ssl which is foundational), so Windows maintains a lock on the file.
Solution: Move instead of delete
The key insight is that while Windows prevents deletion of in-use DLLs, it does allow renaming or moving them to another location (as long as it's on the same filesystem).
Move the in-use DLL to a temporary directory (which works even if the file is in use) Place the new version where the old one was The temporary directory can be cleaned up on next application start
import ssl
import os
import shutil
# Create a temp directory for old files
temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "old_files_temp")
if not os.path.exists(temp_dir):
os.makedirs(temp_dir)
ssl_filename = ssl._ssl.__file__
# Move the file
shutil.move(ssl_filename, os.path.join(temp_dir, os.path.basename(ssl_filename)))
# Now you can move the new version into place
new_ssl_path = "path/to/new/_ssl.pyd" # Path to your new version
shutil.move(new_ssl_path, ssl_filename)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With