1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2009 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
29 #include <sys/types.h>
42 unsigned char in
[FD_SETSIZE
/ CHAR_BIT
];
43 unsigned char out
[FD_SETSIZE
/ CHAR_BIT
];
46 /* Declare data structures for ntdll functions. */
47 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
49 ULONG NamedPipeConfiguration
;
50 ULONG MaximumInstances
;
51 ULONG CurrentInstances
;
53 ULONG ReadDataAvailable
;
55 ULONG WriteQuotaAvailable
;
58 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
60 typedef struct _IO_STATUS_BLOCK
66 ULONG_PTR Information
;
67 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
69 typedef enum _FILE_INFORMATION_CLASS
{
70 FilePipeLocalInformation
= 24
71 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
73 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
74 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
80 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
83 IsSocketHandle(HANDLE h
)
87 if (IsConsoleHandle (h
))
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;
97 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
100 win32_poll_handle (HANDLE h
, int fd
, struct bitset
*rbits
, struct bitset
*wbits
,
101 struct bitset
*xbits
)
103 BOOL read
, write
, except
;
105 INPUT_RECORD
*irbuffer
;
106 DWORD avail
, nbuffer
;
108 IO_STATUS_BLOCK iosb
;
109 FILE_PIPE_LOCAL_INFORMATION fpli
;
110 static PNtQueryInformationFile NtQueryInformationFile
;
111 static BOOL once_only
;
113 read
= write
= except
= FALSE
;
114 switch (GetFileType (h
))
124 NtQueryInformationFile
= (PNtQueryInformationFile
)
125 GetProcAddress (GetModuleHandle ("ntdll.dll"),
126 "NtQueryInformationFile");
130 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
138 /* It was the write-end of the pipe. Check if it is writable.
139 If NtQueryInformationFile fails, optimistically assume the pipe is
140 writable. This could happen on Win9x, where NtQueryInformationFile
141 is not available, or if we inherit a pipe that doesn't permit
142 FILE_READ_ATTRIBUTES access on the write end (I think this should
143 not happen since WinXP SP2; WINE seems fine too). Otherwise,
144 ensure that enough space is available for atomic writes. */
145 memset (&iosb
, 0, sizeof (iosb
));
146 memset (&fpli
, 0, sizeof (fpli
));
148 if (!NtQueryInformationFile
149 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
150 FilePipeLocalInformation
)
151 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
152 || (fpli
.OutboundQuota
< PIPE_BUF
&&
153 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
160 if (!(rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
163 ret
= WaitForSingleObject (h
, 0);
164 if (ret
== WAIT_OBJECT_0
)
166 if (!IsConsoleHandle (h
))
173 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
175 /* Screen buffers handles are filtered earlier. */
183 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
184 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
185 if (!bRet
|| avail
== 0)
191 for (i
= 0; i
< avail
; i
++)
192 if (irbuffer
[i
].EventType
== KEY_EVENT
)
198 ret
= WaitForSingleObject (h
, 0);
200 if (ret
== WAIT_OBJECT_0
)
207 if (read
&& (rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
209 rbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
213 if (write
&& (wbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
215 wbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
219 if (except
&& (xbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
221 xbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
229 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
230 struct timeval
*timeout
)
232 static struct timeval tv0
;
233 static HANDLE hEvent
;
234 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
235 fd_set handle_rfds
, handle_wfds
, handle_xfds
;
236 struct bitset rbits
, wbits
, xbits
;
237 unsigned char anyfds_in
[FD_SETSIZE
/ CHAR_BIT
];
238 DWORD ret
, wait_timeout
, nhandles
, nsock
, nbuffer
;
242 if (nfds
> FD_SETSIZE
)
246 wait_timeout
= INFINITE
;
249 wait_timeout
= timeout
->tv_sec
+ timeout
->tv_usec
/ 1000;
251 /* select is also used as a portable usleep. */
252 if (!rfds
&& !wfds
&& !xfds
)
254 Sleep (wait_timeout
);
260 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
262 handle_array
[0] = hEvent
;
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. */
270 memset (&rbits
, 0, sizeof (rbits
));
271 memset (&wbits
, 0, sizeof (wbits
));
272 memset (&xbits
, 0, sizeof (xbits
));
273 memset (anyfds_in
, 0, sizeof (anyfds_in
));
275 for (i
= 0; i
< rfds
->fd_count
; i
++)
277 fd
= rfds
->fd_array
[i
];
278 h
= (HANDLE
) _get_osfhandle (fd
);
279 if (IsConsoleHandle (h
)
280 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
283 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
284 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
287 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
290 for (i
= 0; i
< wfds
->fd_count
; i
++)
292 fd
= wfds
->fd_array
[i
];
293 h
= (HANDLE
) _get_osfhandle (fd
);
294 if (IsConsoleHandle (h
)
295 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
298 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
299 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
302 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
305 for (i
= 0; i
< xfds
->fd_count
; i
++)
307 fd
= xfds
->fd_array
[i
];
308 xbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
309 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
312 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
314 /* Zero all the fd_sets, including the application's. */
318 FD_ZERO (&handle_rfds
);
319 FD_ZERO (&handle_wfds
);
320 FD_ZERO (&handle_xfds
);
322 /* Classify handles. Create fd sets for sockets, poll the others. */
323 for (i
= 0; i
< nfds
; i
++)
327 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
330 h
= (HANDLE
) _get_osfhandle (i
);
337 if (IsSocketHandle (h
))
339 int requested
= FD_CLOSE
;
341 /* See above; socket handles are mapped onto select, but we
342 need to map descriptors to handles. */
343 if (rbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
345 requested
|= FD_READ
| FD_ACCEPT
;
346 FD_SET ((SOCKET
) h
, rfds
);
347 FD_SET ((SOCKET
) h
, &handle_rfds
);
349 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
351 requested
|= FD_WRITE
| FD_CONNECT
;
352 FD_SET ((SOCKET
) h
, wfds
);
353 FD_SET ((SOCKET
) h
, &handle_wfds
);
355 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
358 FD_SET ((SOCKET
) h
, xfds
);
359 FD_SET ((SOCKET
) h
, &handle_xfds
);
362 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
367 handle_array
[nhandles
++] = h
;
369 /* Poll now. If we get an event, do not wait below. */
370 if (wait_timeout
!= 0
371 && win32_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
))
376 if (wait_timeout
== 0 || nsock
== 0)
380 /* See if we need to wait in the loop below. If any select is ready,
381 do MsgWaitForMultipleObjects anyway to dispatch messages, but
382 no need to call select again. */
383 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
386 /* Restore the fd_sets for the other select we do below. */
387 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
388 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
389 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
397 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
398 wait_timeout
, QS_ALLINPUT
);
400 if (ret
== WAIT_OBJECT_0
+ nhandles
)
402 /* new input of some other kind */
404 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
406 TranslateMessage (&msg
);
407 DispatchMessage (&msg
);
414 /* If we haven't done it yet, check the status of the sockets. */
415 if (rc
== 0 && nsock
> 0)
416 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
418 /* Now fill in the results. */
423 /* Place a sentinel at the end of the array. */
424 handle_array
[nhandles
] = NULL
;
426 for (i
= 0; i
< nfds
; i
++)
428 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
431 h
= (HANDLE
) _get_osfhandle (i
);
432 if (h
!= handle_array
[nhandles
])
434 /* Perform handle->descriptor mapping. Don't update rc, as these
435 results are counted in the return value of Winsock's select. */
436 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
437 if (FD_ISSET (h
, &handle_rfds
))
439 if (FD_ISSET (h
, &handle_wfds
))
441 if (FD_ISSET (h
, &handle_xfds
))
448 win32_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
);
449 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
454 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
459 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
470 #else /* ! Native Win32. */
472 #include <sys/select.h>
477 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
478 struct timeval
*timeout
)
480 /* Interix 3.5 has a bug: it does not support nfds == 0. */
488 return select (nfds
, rfds
, wfds
, xfds
, timeout
);