Greetings! Apologies in advance for the length of this post; after many days of scouring Python and Windows news groups, I've seen reports of issues similar to mine, but no cause or resolution other than re-trying an operation. I'm in no way a Windows programmer; I've spent my entire career on Unix/Linux, so the Windows ways are a bit of a mystery to me at times. That being said, I'm hoping that someone might shed some light on something stupid I've done (limited to this topic, please) or that I might actually save someone else's time when they see this post.
I have been tracking down random descriptor issues with a multithreaded Windows service written in Python. The issue presents itself as "bad file descriptor", "attempt to read from something that is not a socket", and various errors closing files and sockets. In my service, I needed to be able to open a file with FILE_FLAG_BACKUP_SEMANTICS, create a Python file object and pass it off to another method to read. Since the Python posix file open() method doesn't provide a way to pass special Windozy flags, and I didn't see a way of setting that post-open, I followed a pattern that I found that looks like this: h = win32file.CreateFile( fname, win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, win32file.FILE_FLAG_BACKUP_SEMANTICS, None ) fd = msvcrt.open_osfhandle(h, os.O_RDONLY) f = os.fdopen(fd, 'rb') That worked well and I was able to pass that 'f' off to be handled like any other file-like object. However, my multi-threaded service would randomly raise file descriptor errors reading files, logging and writing data on the network. What I found is that the file descriptors in the PyHANDLE and the file object seem to be somewhat out of sync during garbage collection. Closing the PyHANDLE leaves the file object with an invalid descriptor, and closing the file object leaves the PyHANDLE with an invalid descriptor, but only sometimes. If you put the code above into a loop, most of the time it will raise with a bad file descriptor error as the old objects go out of scope and are collected. I tried to remedy that by first calling CloseHandle() on the PyHANDLE and then close() on the file object (wrapped in a a try:..except IOError to deal with the already closed descriptor), and that makes the loop run, but still causes problems with other threads that just happen to open/close a d escriptor at the right/wrong time. So, my completely inexperienced (in Windows) empirical diagnosis is that there is some sort of synchronization issue between the msvcrt library and the CPython runtime that results in descriptors being shared among file and socket objects in a multithreaded application. At any rate, I replaced the CreateFile()/msvcrt.open_osfhandle()/os.fdopen() with a wrapper class that uses CreateFile()/ReadFile() and provides a minimal set of file-like object methods and all of my file descriptor and socket problems went away, so either I'm correct, or I just moved my problem. As I said in the beginning of this epic, I'm no more sure that I've found a problem with the underlying classes that manage descriptors on Windows than I've just replaced my own bad code with other not-as-bad code, but I hope that this rings a bell for someone that can set me straight. Thanks, Scott Leerssen _______________________________________________ python-win32 mailing list python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32