]> code.delx.au - pulseaudio/blob - src/pulsecore/poll.c
Merge dead branch 'prepare-0.9.10'
[pulseaudio] / src / pulsecore / poll.c
1
2 /***
3 This file is part of PulseAudio.
4
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 /***
24 Based on work for the GNU C Library.
25 Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
26 ***/
27
28 /* Poll the file descriptors described by the NFDS structures starting at
29 FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
30 an event to occur; if TIMEOUT is -1, block until an event occurs.
31 Returns the number of file descriptors with events, zero if timed out,
32 or -1 for errors. */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <errno.h>
39
40 #ifdef HAVE_SYS_SELECT_H
41 #include <sys/select.h>
42 #endif
43
44 #include "winsock.h"
45
46 #ifndef HAVE_POLL_H
47
48 #include <pulsecore/core-util.h>
49
50 #include "poll.h"
51
52 int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
53 struct timeval tv;
54 fd_set rset, wset, xset;
55 struct pollfd *f;
56 int ready;
57 int maxfd = 0;
58 char data[64];
59
60 FD_ZERO (&rset);
61 FD_ZERO (&wset);
62 FD_ZERO (&xset);
63
64 if (nfds == 0) {
65 if (timeout >= 0) {
66 pa_msleep(timeout);
67 return 0;
68 }
69
70 #ifdef OS_IS_WIN32
71 /*
72 * Windows does not support signals properly so waiting for them would
73 * mean a deadlock.
74 */
75 pa_msleep(100);
76 return 0;
77 #else
78 return select(0, NULL, NULL, NULL, NULL);
79 #endif
80 }
81
82 for (f = fds; f < &fds[nfds]; ++f) {
83 if (f->fd != -1) {
84 if (f->events & POLLIN)
85 FD_SET (f->fd, &rset);
86 if (f->events & POLLOUT)
87 FD_SET (f->fd, &wset);
88 if (f->events & POLLPRI)
89 FD_SET (f->fd, &xset);
90 if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
91 maxfd = f->fd;
92 }
93 }
94
95 tv.tv_sec = timeout / 1000;
96 tv.tv_usec = (timeout % 1000) * 1000;
97
98 ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
99 SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
100 SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
101 if ((ready == -1) && (errno == EBADF)) {
102 ready = 0;
103
104 FD_ZERO (&rset);
105 FD_ZERO (&wset);
106 FD_ZERO (&xset);
107
108 maxfd = -1;
109
110 for (f = fds; f < &fds[nfds]; ++f) {
111 if (f->fd != -1) {
112 fd_set sngl_rset, sngl_wset, sngl_xset;
113
114 FD_ZERO (&sngl_rset);
115 FD_ZERO (&sngl_wset);
116 FD_ZERO (&sngl_xset);
117
118 if (f->events & POLLIN)
119 FD_SET (f->fd, &sngl_rset);
120 if (f->events & POLLOUT)
121 FD_SET (f->fd, &sngl_wset);
122 if (f->events & POLLPRI)
123 FD_SET (f->fd, &sngl_xset);
124 if (f->events & (POLLIN|POLLOUT|POLLPRI)) {
125 struct timeval singl_tv;
126
127 singl_tv.tv_sec = 0;
128 singl_tv.tv_usec = 0;
129
130 if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset,
131 SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
132 SELECT_TYPE_ARG5 &singl_tv) != -1) {
133 if (f->events & POLLIN)
134 FD_SET (f->fd, &rset);
135 if (f->events & POLLOUT)
136 FD_SET (f->fd, &wset);
137 if (f->events & POLLPRI)
138 FD_SET (f->fd, &xset);
139 if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
140 maxfd = f->fd;
141 ++ready;
142 } else if (errno == EBADF)
143 f->revents |= POLLNVAL;
144 }
145 }
146 }
147
148 if (ready) {
149 /* Linux alters the tv struct... but it shouldn't matter here ...
150 * as we're going to be a little bit out anyway as we've just eaten
151 * more than a couple of cpu cycles above */
152 ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
153 SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
154 SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
155 }
156 }
157
158 #ifdef OS_IS_WIN32
159 errno = WSAGetLastError();
160 #endif
161
162 if (ready > 0) {
163 ready = 0;
164 for (f = fds; f < &fds[nfds]; ++f) {
165 f->revents = 0;
166 if (f->fd != -1) {
167 if (FD_ISSET (f->fd, &rset)) {
168 /* support for POLLHUP. An hung up descriptor does not
169 increase the return value! */
170 if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
171 if (errno == ESHUTDOWN || errno == ECONNRESET ||
172 errno == ECONNABORTED || errno == ENETRESET) {
173 fprintf(stderr, "Hangup\n");
174 f->revents |= POLLHUP;
175 }
176 }
177
178 if (f->revents == 0)
179 f->revents |= POLLIN;
180 }
181 if (FD_ISSET (f->fd, &wset))
182 f->revents |= POLLOUT;
183 if (FD_ISSET (f->fd, &xset))
184 f->revents |= POLLPRI;
185 }
186 if (f->revents)
187 ready++;
188 }
189 }
190
191 return ready;
192 }
193
194 #endif /* HAVE_SYS_POLL_H */