1
# NOTE: win32 support is currently experimental, and not recommended
11
# See: http://msdn.microsoft.com/en-us/library/ms738573(VS.85).aspx
12
ioctlsocket = ctypes.windll.ws2_32.ioctlsocket
13
ioctlsocket.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.LONG, ctypes.wintypes.ULONG)
14
ioctlsocket.restype = ctypes.c_int
16
# See: http://msdn.microsoft.com/en-us/library/ms724935(VS.85).aspx
17
SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
18
SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)
19
SetHandleInformation.restype = ctypes.wintypes.BOOL
21
HANDLE_FLAG_INHERIT = 0x00000001
36
def fcntl(fd, op, arg=0):
37
if op == F_GETFD or op == F_GETFL:
40
# Check that the flag is CLOEXEC and translate
42
success = SetHandleInformation(fd, HANDLE_FLAG_INHERIT, arg)
44
raise ctypes.GetLastError()
46
raise ValueError("Unsupported arg")
48
## Check that the flag is NONBLOCK and translate
49
#if arg == os.O_NONBLOCK:
51
#result = ioctlsocket(fd, FIONBIO, 1)
53
#raise ctypes.GetLastError()
55
#raise ValueError("Unsupported arg")
57
raise ValueError("Unsupported op")
61
"""Create an OS independent asynchronous pipe"""
63
# Based on Zope async.py: http://svn.zope.org/zc.ngi/trunk/src/zc/ngi/async.py
65
self.writer = socket.socket()
66
# Disable buffering -- pulling the trigger sends 1 byte,
67
# and we want that sent immediately, to wake up ASAP.
68
self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
73
# Bind to a local port; for efficiency, let the OS pick
75
# Unfortunately, stress tests showed that we may not
76
# be able to connect to that port ("Address already in
77
# use") despite that the OS picked it. This appears
78
# to be a race bug in the Windows socket implementation.
79
# So we loop until a connect() succeeds (almost always
80
# on the first try). See the long thread at
81
# http://mail.zope.org/pipermail/zope/2005-July/160433.html
82
# for hideous details.
84
a.bind(("127.0.0.1", 0))
85
connect_address = a.getsockname() # assigned (host, port) pair
88
self.writer.connect(connect_address)
90
except socket.error, detail:
91
if detail[0] != errno.WSAEADDRINUSE:
92
# "Address already in use" is the only error
93
# I've seen on two WinXP Pro SP2 boxes, under
94
# Pythons 2.3.5 and 2.4.1.
96
# (10048, 'Address already in use')
97
# assert count <= 2 # never triggered in Tim's tests
98
if count >= 10: # I've never seen it go above 2
101
raise socket.error("Cannot bind trigger!")
102
# Close `a` and try again. Note: I originally put a short
103
# sleep() here, but it didn't appear to help or hurt.
106
self.reader, addr = a.accept()
107
self.reader.setblocking(0)
108
self.writer.setblocking(0)
110
self.reader_fd = self.reader.fileno()
113
"""Emulate a file descriptors read method"""
115
return self.reader.recv(1)
116
except socket.error, ex:
117
if ex.args[0] == errno.EWOULDBLOCK:
121
def write(self, data):
122
"""Emulate a file descriptors write method"""
123
return self.writer.send(data)