comparison lib/select.c @ 11852:c9032834d889

Fix polling for writeability of a screen buffer. * lib/poll.c: Distinguish input and screen buffers for the Win32 implementation. * lib/select.c: Likewise.
author Paolo Bonzini <bonzini@gnu.org>
date Tue, 04 Aug 2009 18:06:07 +0200
parents 2de4c4d41f01
children 02b65a16c35d
comparison
equal deleted inserted replaced
11851:c9727d4e7e5a 11852:c9032834d889
19 with this program; if not, write to the Free Software Foundation, 19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21 21
22 #include <config.h> 22 #include <config.h>
23 #include <alloca.h> 23 #include <alloca.h>
24 #include <assert.h>
24 25
25 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
26 /* Native Win32. */ 27 /* Native Win32. */
27 28
28 #include <sys/types.h> 29 #include <sys/types.h>
74 75
75 #ifndef PIPE_BUF 76 #ifndef PIPE_BUF
76 #define PIPE_BUF 512 77 #define PIPE_BUF 512
77 #endif 78 #endif
78 79
80 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
81
82 static BOOL
83 IsSocketHandle(HANDLE h)
84 {
85 WSANETWORKEVENTS ev;
86
87 if (IsConsoleHandle (h))
88 return FALSE;
89
90 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
91 WSAEnumNetworkEvents instead distinguishes the two correctly. */
92 ev.lNetworkEvents = 0xDEADBEEF;
93 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
94 return ev.lNetworkEvents != 0xDEADBEEF;
95 }
96
79 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */ 97 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
80 98
81 static int 99 static int
82 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits, 100 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
83 struct bitset *xbits) 101 struct bitset *xbits)
136 write = TRUE; 154 write = TRUE;
137 } 155 }
138 break; 156 break;
139 157
140 case FILE_TYPE_CHAR: 158 case FILE_TYPE_CHAR:
159 write = TRUE;
160 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
161 break;
162
141 ret = WaitForSingleObject (h, 0); 163 ret = WaitForSingleObject (h, 0);
142 write = TRUE;
143 if (ret == WAIT_OBJECT_0) 164 if (ret == WAIT_OBJECT_0)
144 { 165 {
166 if (!IsConsoleHandle (h))
167 {
168 read = TRUE;
169 break;
170 }
171
145 nbuffer = avail = 0; 172 nbuffer = avail = 0;
146 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); 173 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
147 if (!bRet || nbuffer == 0) 174
148 except = TRUE; 175 /* Screen buffers handles are filtered earlier. */
176 assert (bRet);
177 if (nbuffer == 0)
178 {
179 except = TRUE;
180 break;
181 }
149 182
150 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); 183 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
151 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); 184 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
152 if (!bRet || avail == 0) 185 if (!bRet || avail == 0)
153 except = TRUE; 186 {
187 except = TRUE;
188 break;
189 }
154 190
155 for (i = 0; i < avail; i++) 191 for (i = 0; i < avail; i++)
156 if (irbuffer[i].EventType == KEY_EVENT) 192 if (irbuffer[i].EventType == KEY_EVENT)
157 read = TRUE; 193 read = TRUE;
158 } 194 }
197 static HANDLE hEvent; 233 static HANDLE hEvent;
198 HANDLE h, handle_array[FD_SETSIZE + 2]; 234 HANDLE h, handle_array[FD_SETSIZE + 2];
199 fd_set handle_rfds, handle_wfds, handle_xfds; 235 fd_set handle_rfds, handle_wfds, handle_xfds;
200 struct bitset rbits, wbits, xbits; 236 struct bitset rbits, wbits, xbits;
201 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT]; 237 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
202 DWORD ret, wait_timeout, nhandles, nsock; 238 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
203 MSG msg; 239 MSG msg;
204 int i, fd, rc; 240 int i, fd, rc;
205 241
206 if (nfds > FD_SETSIZE) 242 if (nfds > FD_SETSIZE)
207 nfds = FD_SETSIZE; 243 nfds = FD_SETSIZE;
225 261
226 handle_array[0] = hEvent; 262 handle_array[0] = hEvent;
227 nhandles = 1; 263 nhandles = 1;
228 nsock = 0; 264 nsock = 0;
229 265
230 /* Copy descriptors to bitsets. */ 266 /* Copy descriptors to bitsets. At the same time, eliminate
267 bits in the "wrong" direction for console input buffers
268 and screen buffers, because screen buffers are waitable
269 and they will block until a character is available. */
231 memset (&rbits, 0, sizeof (rbits)); 270 memset (&rbits, 0, sizeof (rbits));
232 memset (&wbits, 0, sizeof (wbits)); 271 memset (&wbits, 0, sizeof (wbits));
233 memset (&xbits, 0, sizeof (xbits)); 272 memset (&xbits, 0, sizeof (xbits));
234 memset (anyfds_in, 0, sizeof (anyfds_in)); 273 memset (anyfds_in, 0, sizeof (anyfds_in));
235 if (rfds) 274 if (rfds)
236 for (i = 0; i < rfds->fd_count; i++) 275 for (i = 0; i < rfds->fd_count; i++)
237 { 276 {
238 fd = rfds->fd_array[i]; 277 fd = rfds->fd_array[i];
278 h = (HANDLE) _get_osfhandle (fd);
279 if (IsConsoleHandle (h)
280 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
281 continue;
282
239 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 283 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
240 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 284 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
241 } 285 }
242 else 286 else
243 rfds = (fd_set *) alloca (sizeof (fd_set)); 287 rfds = (fd_set *) alloca (sizeof (fd_set));
244 288
245 if (wfds) 289 if (wfds)
246 for (i = 0; i < wfds->fd_count; i++) 290 for (i = 0; i < wfds->fd_count; i++)
247 { 291 {
248 fd = wfds->fd_array[i]; 292 fd = wfds->fd_array[i];
293 h = (HANDLE) _get_osfhandle (fd);
294 if (IsConsoleHandle (h)
295 && GetNumberOfConsoleInputEvents (h, &nbuffer))
296 continue;
297
249 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 298 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
250 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1)); 299 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
251 } 300 }
252 else 301 else
253 wfds = (fd_set *) alloca (sizeof (fd_set)); 302 wfds = (fd_set *) alloca (sizeof (fd_set));
283 { 332 {
284 errno = EBADF; 333 errno = EBADF;
285 return -1; 334 return -1;
286 } 335 }
287 336
288 /* Under Wine, it seems that getsockopt returns 0 for pipes too. 337 if (IsSocketHandle (h))
289 WSAEnumNetworkEvents instead distinguishes the two correctly. */
290 ev.lNetworkEvents = 0xDEADBEEF;
291 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
292 if (ev.lNetworkEvents != 0xDEADBEEF)
293 { 338 {
294 int requested = FD_CLOSE; 339 int requested = FD_CLOSE;
295 340
296 /* See above; socket handles are mapped onto select, but we 341 /* See above; socket handles are mapped onto select, but we
297 need to map descriptors to handles. */ 342 need to map descriptors to handles. */