Mercurial > hg > octave-nkf > gnulib-hg
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. */ |