Open AstraLuma opened 7 years ago
(On POSIX, I'm just using a selector, which seems to be ok.)
The cross-platform solution is to have a background singleton that reads from all the pipes we care about and dispatch to the object that cares about it at the moment. (ie, the home-spun event loop option) Which will be fine until someone wants to coordinate those changes with something that can't be controlled the same way (eg, an external process).
Note: WaitForMultipleObjectsEx()
EDIT: Doesn't work on pipes.
PeekNamedPipe()
does work on anonymous pipes, though.
EDIT: .fileno()
returns some kind of emulated file descriptor with Unix-like semantics, not the actual windows handle. Oddly, Win32 calls want the handle, not the file descriptor.
The winvalve branch tries to use CancelSynchronousIo()
. This doesn't work because CPython's .read()
loops on the C read()
call unless there's a Python exception and an interrupted flag is set. (Or the C read()
not breaking, I didn't dig deep enough to tell the difference.)
The winvalve-peek branch tries to use PeekNamedPipe()
, but fails due to the file descriptor emulation layer and the true win32 handles being hidden from us. (Basically, _pipe()
vs CreatePipe()
)
Oh, and just as a reminder: These might need to be used with other things (standard IO, files, etc)
So I think ReadFile()
/CancelSyncronousIO()
is the way to go on this, because it should support whatever kind of file-like that gets passed in. To avoid the file descriptor/handle issue, use _get_osfhandle()
(Py). (Note that this handle is managed by the ms c runtime and should NOT be closed by slug. Slug should maintain a reference to the Python file object associated with the file descriptor and delete its copy of the handle before letting the file object fall out of scope.)
Both
Valve
andQuickConnect
need extremely special windows implementations..read()
will only break on an actual triggered interrupt, not just a faked exception throughPyThreadState_SetAsyncExc()
.So I think we need to use win32's
ReadFile()
manually in conjunction withCancelSynchronousIo()
in order to not read an extra block when switching.