~ubuntu-branches/ubuntu/oneiric/gnutls26/oneiric

« back to all changes in this revision

Viewing changes to gl/select.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-05-20 13:07:18 UTC
  • mfrom: (12.1.11 sid)
  • Revision ID: james.westby@ubuntu.com-20110520130718-db41dybbanzfvlji
Tags: 2.10.5-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Fix build failure with --no-add-needed.
  - Build for multiarch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Emulation for select(2)
2
2
   Contributed by Paolo Bonzini.
3
3
 
4
 
   Copyright 2008-2009 Free Software Foundation, Inc.
 
4
   Copyright 2008-2010 Free Software Foundation, Inc.
5
5
 
6
6
   This file is part of gnulib.
7
7
 
21
21
 
22
22
#include <config.h>
23
23
#include <alloca.h>
 
24
#include <assert.h>
24
25
 
25
26
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
26
27
/* Native Win32.  */
70
71
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
71
72
 
72
73
typedef DWORD (WINAPI *PNtQueryInformationFile)
73
 
         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
 
74
         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
74
75
 
75
76
#ifndef PIPE_BUF
76
 
#define PIPE_BUF        512
 
77
#define PIPE_BUF        512
77
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
97
/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
80
98
 
81
99
static int
82
100
win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
83
 
                   struct bitset *xbits)
 
101
                   struct bitset *xbits)
84
102
{
85
103
  BOOL read, write, except;
86
104
  int i, ret;
102
120
 
103
121
    case FILE_TYPE_PIPE:
104
122
      if (!once_only)
105
 
        {
106
 
          NtQueryInformationFile = (PNtQueryInformationFile)
107
 
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
108
 
                            "NtQueryInformationFile");
109
 
          once_only = TRUE;
110
 
        }
 
123
        {
 
124
          NtQueryInformationFile = (PNtQueryInformationFile)
 
125
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
 
126
                            "NtQueryInformationFile");
 
127
          once_only = TRUE;
 
128
        }
111
129
 
112
130
      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
113
 
        {
114
 
          if (avail)
115
 
            read = TRUE;
116
 
        }
 
131
        {
 
132
          if (avail)
 
133
            read = TRUE;
 
134
        }
117
135
 
118
136
      else
119
 
        {
120
 
          /* It was the write-end of the pipe.  Check if it is writable.
121
 
             If NtQueryInformationFile fails, optimistically assume the pipe is
122
 
             writable.  This could happen on Win9x, where NtQueryInformationFile
123
 
             is not available, or if we inherit a pipe that doesn't permit
124
 
             FILE_READ_ATTRIBUTES access on the write end (I think this should
125
 
             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
126
 
             ensure that enough space is available for atomic writes.  */
 
137
        {
 
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.  */
127
145
          memset (&iosb, 0, sizeof (iosb));
128
146
          memset (&fpli, 0, sizeof (fpli));
129
147
 
130
148
          if (!NtQueryInformationFile
131
149
              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
132
 
                                         FilePipeLocalInformation)
133
 
              || fpli.WriteQuotaAvailable >= PIPE_BUF
134
 
              || (fpli.OutboundQuota < PIPE_BUF &&
135
 
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
136
 
            write = TRUE;
137
 
        }
 
150
                                         FilePipeLocalInformation)
 
151
              || fpli.WriteQuotaAvailable >= PIPE_BUF
 
152
              || (fpli.OutboundQuota < PIPE_BUF &&
 
153
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
 
154
            write = TRUE;
 
155
        }
138
156
      break;
139
157
 
140
158
    case FILE_TYPE_CHAR:
 
159
      write = TRUE;
 
160
      if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
 
161
        break;
 
162
 
141
163
      ret = WaitForSingleObject (h, 0);
142
 
      write = TRUE;
143
164
      if (ret == WAIT_OBJECT_0)
144
165
        {
145
 
          nbuffer = avail = 0;
146
 
          bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
147
 
          if (!bRet || nbuffer == 0)
148
 
            except = TRUE;
149
 
 
150
 
          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
151
 
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
152
 
          if (!bRet || avail == 0)
153
 
            except = TRUE;
154
 
 
155
 
          for (i = 0; i < avail; i++)
156
 
            if (irbuffer[i].EventType == KEY_EVENT)
157
 
              read = TRUE;
158
 
        }
 
166
          if (!IsConsoleHandle (h))
 
167
            {
 
168
              read = TRUE;
 
169
              break;
 
170
            }
 
171
 
 
172
          nbuffer = avail = 0;
 
173
          bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
 
174
 
 
175
          /* Screen buffers handles are filtered earlier.  */
 
176
          assert (bRet);
 
177
          if (nbuffer == 0)
 
178
            {
 
179
              except = TRUE;
 
180
              break;
 
181
            }
 
182
 
 
183
          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
 
184
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
 
185
          if (!bRet || avail == 0)
 
186
            {
 
187
              except = TRUE;
 
188
              break;
 
189
            }
 
190
 
 
191
          for (i = 0; i < avail; i++)
 
192
            if (irbuffer[i].EventType == KEY_EVENT)
 
193
              read = TRUE;
 
194
        }
159
195
      break;
160
196
 
161
197
    default:
199
235
  fd_set handle_rfds, handle_wfds, handle_xfds;
200
236
  struct bitset rbits, wbits, xbits;
201
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
239
  MSG msg;
204
240
  int i, fd, rc;
205
241
 
210
246
    wait_timeout = INFINITE;
211
247
  else
212
248
    {
213
 
      wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
 
249
      wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
214
250
 
215
251
      /* select is also used as a portable usleep.  */
216
252
      if (!rfds && !wfds && !xfds)
227
263
  nhandles = 1;
228
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
270
  memset (&rbits, 0, sizeof (rbits));
232
271
  memset (&wbits, 0, sizeof (wbits));
233
272
  memset (&xbits, 0, sizeof (xbits));
236
275
    for (i = 0; i < rfds->fd_count; i++)
237
276
      {
238
277
        fd = rfds->fd_array[i];
 
278
        h = (HANDLE) _get_osfhandle (fd);
 
279
        if (IsConsoleHandle (h)
 
280
            && !GetNumberOfConsoleInputEvents (h, &nbuffer))
 
281
          continue;
 
282
 
239
283
        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
240
284
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
241
285
      }
246
290
    for (i = 0; i < wfds->fd_count; i++)
247
291
      {
248
292
        fd = wfds->fd_array[i];
 
293
        h = (HANDLE) _get_osfhandle (fd);
 
294
        if (IsConsoleHandle (h)
 
295
            && GetNumberOfConsoleInputEvents (h, &nbuffer))
 
296
          continue;
 
297
 
249
298
        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
250
299
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
251
300
      }
273
322
  /* Classify handles.  Create fd sets for sockets, poll the others. */
274
323
  for (i = 0; i < nfds; i++)
275
324
    {
276
 
      WSANETWORKEVENTS ev;
277
 
 
278
325
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
279
 
        continue;
 
326
        continue;
280
327
 
281
328
      h = (HANDLE) _get_osfhandle (i);
282
329
      if (!h)
283
330
        {
284
 
          errno = EBADF;
285
 
          return -1;
 
331
          errno = EBADF;
 
332
          return -1;
286
333
        }
287
334
 
288
 
      /* Under Wine, it seems that getsockopt returns 0 for pipes too.
289
 
         WSAEnumNetworkEvents instead distinguishes the two correctly.  */
290
 
      ev.lNetworkEvents = 0xDEADBEEF;
291
 
      WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
292
 
      if (ev.lNetworkEvents != 0xDEADBEEF)
 
335
      if (IsSocketHandle (h))
293
336
        {
294
337
          int requested = FD_CLOSE;
295
338
 
296
339
          /* See above; socket handles are mapped onto select, but we
297
 
             need to map descriptors to handles.  */
 
340
             need to map descriptors to handles.  */
298
341
          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
299
 
            {
 
342
            {
300
343
              requested |= FD_READ | FD_ACCEPT;
301
 
              FD_SET ((SOCKET) h, rfds);
302
 
              FD_SET ((SOCKET) h, &handle_rfds);
303
 
            }
 
344
              FD_SET ((SOCKET) h, rfds);
 
345
              FD_SET ((SOCKET) h, &handle_rfds);
 
346
            }
304
347
          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
305
 
            {
 
348
            {
306
349
              requested |= FD_WRITE | FD_CONNECT;
307
 
              FD_SET ((SOCKET) h, wfds);
308
 
              FD_SET ((SOCKET) h, &handle_wfds);
309
 
            }
 
350
              FD_SET ((SOCKET) h, wfds);
 
351
              FD_SET ((SOCKET) h, &handle_wfds);
 
352
            }
310
353
          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
311
 
            {
 
354
            {
312
355
              requested |= FD_OOB;
313
 
              FD_SET ((SOCKET) h, xfds);
314
 
              FD_SET ((SOCKET) h, &handle_xfds);
315
 
            }
 
356
              FD_SET ((SOCKET) h, xfds);
 
357
              FD_SET ((SOCKET) h, &handle_xfds);
 
358
            }
316
359
 
317
360
          WSAEventSelect ((SOCKET) h, hEvent, requested);
318
 
          nsock++;
 
361
          nsock++;
319
362
        }
320
363
      else
321
364
        {
322
365
          handle_array[nhandles++] = h;
323
366
 
324
 
          /* Poll now.  If we get an event, do not wait below.  */
 
367
          /* Poll now.  If we get an event, do not wait below.  */
325
368
          if (wait_timeout != 0
326
 
              && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
327
 
            wait_timeout = 0;
 
369
              && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
 
370
            wait_timeout = 0;
328
371
        }
329
372
    }
330
373
 
337
380
         no need to call select again.  */
338
381
      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
339
382
      if (rc == 0)
340
 
        {
341
 
          /* Restore the fd_sets for the other select we do below.  */
 
383
        {
 
384
          /* Restore the fd_sets for the other select we do below.  */
342
385
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
343
386
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
344
387
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
345
 
        }
 
388
        }
346
389
      else
347
390
        wait_timeout = 0;
348
391
    }
350
393
  for (;;)
351
394
    {
352
395
      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
353
 
                                       wait_timeout, QS_ALLINPUT);
 
396
                                       wait_timeout, QS_ALLINPUT);
354
397
 
355
398
      if (ret == WAIT_OBJECT_0 + nhandles)
356
 
        {
 
399
        {
357
400
          /* new input of some other kind */
358
 
          BOOL bRet;
 
401
          BOOL bRet;
359
402
          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
360
403
            {
361
404
              TranslateMessage (&msg);
362
405
              DispatchMessage (&msg);
363
406
            }
364
 
        }
 
407
        }
365
408
      else
366
 
        break;
 
409
        break;
367
410
    }
368
411
 
369
412
  /* If we haven't done it yet, check the status of the sockets.  */
381
424
  for (i = 0; i < nfds; i++)
382
425
    {
383
426
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
384
 
        continue;
 
427
        continue;
385
428
 
386
429
      h = (HANDLE) _get_osfhandle (i);
387
430
      if (h != handle_array[nhandles])
388
 
        {
389
 
          /* Perform handle->descriptor mapping.  Don't update rc, as these
390
 
             results are counted in the return value of Winsock's select.  */
 
431
        {
 
432
          /* Perform handle->descriptor mapping.  Don't update rc, as these
 
433
             results are counted in the return value of Winsock's select.  */
391
434
          WSAEventSelect ((SOCKET) h, NULL, 0);
392
435
          if (FD_ISSET (h, &handle_rfds))
393
436
            FD_SET (i, rfds);
395
438
            FD_SET (i, wfds);
396
439
          if (FD_ISSET (h, &handle_xfds))
397
440
            FD_SET (i, xfds);
398
 
        }
 
441
        }
399
442
      else
400
443
        {
401
444
          /* Not a socket.  */
403
446
          win32_poll_handle (h, i, &rbits, &wbits, &xbits);
404
447
          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
405
448
            {
406
 
              rc++;
407
 
              FD_SET (i, rfds);
408
 
            }
 
449
              rc++;
 
450
              FD_SET (i, rfds);
 
451
            }
409
452
          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
410
453
            {
411
 
              rc++;
412
 
              FD_SET (i, wfds);
413
 
            }
 
454
              rc++;
 
455
              FD_SET (i, wfds);
 
456
            }
414
457
          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
415
458
            {
416
 
              rc++;
417
 
              FD_SET (i, xfds);
418
 
            }
 
459
              rc++;
 
460
              FD_SET (i, xfds);
 
461
            }
419
462
        }
420
463
    }
421
464