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