Browse code

os: replace select with poll

Select has limitations on the fd values it could accept and silently
breaks when it is reached.

Luca Barbato authored on 2011/01/28 11:12:21
Showing 8 changed files
... ...
@@ -236,7 +236,6 @@ int ff_socket_nonblock(int socket, int enable)
236 236
 }
237 237
 #endif /* CONFIG_NETWORK */
238 238
 
239
-#if CONFIG_FFSERVER
240 239
 #if !HAVE_POLL_H
241 240
 int poll(struct pollfd *fds, nfds_t numfds, int timeout)
242 241
 {
... ...
@@ -305,5 +304,3 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
305 305
     return rc;
306 306
 }
307 307
 #endif /* HAVE_POLL_H */
308
-#endif /* CONFIG_FFSERVER */
309
-
... ...
@@ -34,8 +34,8 @@
34 34
 #include "network.h"
35 35
 #include "os_support.h"
36 36
 #include <fcntl.h>
37
-#if HAVE_SYS_SELECT_H
38
-#include <sys/select.h>
37
+#if HAVE_POLL_H
38
+#include <sys/poll.h>
39 39
 #endif
40 40
 #include <sys/time.h>
41 41
 
... ...
@@ -221,9 +221,9 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
221 221
     RTPContext *s = h->priv_data;
222 222
     struct sockaddr_storage from;
223 223
     socklen_t from_len;
224
-    int len, fd_max, n;
225
-    fd_set rfds;
226
-    struct timeval tv;
224
+    int len, n;
225
+    struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
226
+
227 227
 #if 0
228 228
     for(;;) {
229 229
         from_len = sizeof(from);
... ...
@@ -242,18 +242,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
242 242
         if (url_interrupt_cb())
243 243
             return AVERROR(EINTR);
244 244
         /* build fdset to listen to RTP and RTCP packets */
245
-        FD_ZERO(&rfds);
246
-        fd_max = s->rtp_fd;
247
-        FD_SET(s->rtp_fd, &rfds);
248
-        if (s->rtcp_fd > fd_max)
249
-            fd_max = s->rtcp_fd;
250
-        FD_SET(s->rtcp_fd, &rfds);
251
-        tv.tv_sec = 0;
252
-        tv.tv_usec = 100 * 1000;
253
-        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
245
+        n = poll(p, 2, 100);
254 246
         if (n > 0) {
255 247
             /* first try RTCP */
256
-            if (FD_ISSET(s->rtcp_fd, &rfds)) {
248
+            if (p[1].revents & POLLIN) {
257 249
                 from_len = sizeof(from);
258 250
                 len = recvfrom (s->rtcp_fd, buf, size, 0,
259 251
                                 (struct sockaddr *)&from, &from_len);
... ...
@@ -266,7 +258,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
266 266
                 break;
267 267
             }
268 268
             /* then RTP */
269
-            if (FD_ISSET(s->rtp_fd, &rfds)) {
269
+            if (p[0].revents & POLLIN) {
270 270
                 from_len = sizeof(from);
271 271
                 len = recvfrom (s->rtp_fd, buf, size, 0,
272 272
                                 (struct sockaddr *)&from, &from_len);
... ...
@@ -26,8 +26,8 @@
26 26
 #include "avformat.h"
27 27
 
28 28
 #include <sys/time.h>
29
-#if HAVE_SYS_SELECT_H
30
-#include <sys/select.h>
29
+#if HAVE_POLL_H
30
+#include <poll.h>
31 31
 #endif
32 32
 #include <strings.h>
33 33
 #include "internal.h"
... ...
@@ -44,11 +44,11 @@
44 44
 //#define DEBUG
45 45
 //#define DEBUG_RTP_TCP
46 46
 
47
-/* Timeout values for socket select, in ms,
47
+/* Timeout values for socket poll, in ms,
48 48
  * and read_packet(), in seconds  */
49
-#define SELECT_TIMEOUT_MS 100
49
+#define POLL_TIMEOUT_MS 100
50 50
 #define READ_PACKET_TIMEOUT_S 10
51
-#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS
51
+#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
52 52
 #define SDP_MAX_SIZE 16384
53 53
 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
54 54
 
... ...
@@ -429,8 +429,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
429 429
     }
430 430
 }
431 431
 
432
+/**
433
+ * Parse the sdp description and allocate the rtp streams and the
434
+ * pollfd array used for udp ones.
435
+ */
436
+
432 437
 int ff_sdp_parse(AVFormatContext *s, const char *content)
433 438
 {
439
+    RTSPState *rt = s->priv_data;
434 440
     const char *p;
435 441
     int letter;
436 442
     /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
... ...
@@ -470,6 +476,8 @@ int ff_sdp_parse(AVFormatContext *s, const char *content)
470 470
         if (*p == '\n')
471 471
             p++;
472 472
     }
473
+    rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
474
+    if (!rt->p) return AVERROR(ENOMEM);
473 475
     return 0;
474 476
 }
475 477
 #endif /* CONFIG_RTPDEC */
... ...
@@ -531,6 +539,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
531 531
         av_close_input_stream (rt->asf_ctx);
532 532
         rt->asf_ctx = NULL;
533 533
     }
534
+    av_free(rt->p);
534 535
     av_free(rt->recvbuf);
535 536
 }
536 537
 
... ...
@@ -1554,55 +1563,51 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
1554 1554
 {
1555 1555
     RTSPState *rt = s->priv_data;
1556 1556
     RTSPStream *rtsp_st;
1557
-    fd_set rfds;
1558
-    int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
1559
-    struct timeval tv;
1557
+    int n, i, ret, tcp_fd, timeout_cnt = 0;
1558
+    int max_p = 0;
1559
+    struct pollfd *p = rt->p;
1560 1560
 
1561 1561
     for (;;) {
1562 1562
         if (url_interrupt_cb())
1563 1563
             return AVERROR(EINTR);
1564 1564
         if (wait_end && wait_end - av_gettime() < 0)
1565 1565
             return AVERROR(EAGAIN);
1566
-        FD_ZERO(&rfds);
1566
+        max_p = 0;
1567 1567
         if (rt->rtsp_hd) {
1568
-            tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
1569
-            FD_SET(tcp_fd, &rfds);
1568
+            tcp_fd = url_get_file_handle(rt->rtsp_hd);
1569
+            p[max_p].fd = tcp_fd;
1570
+            p[max_p++].events = POLLIN;
1570 1571
         } else {
1571
-            fd_max = 0;
1572 1572
             tcp_fd = -1;
1573 1573
         }
1574 1574
         for (i = 0; i < rt->nb_rtsp_streams; i++) {
1575 1575
             rtsp_st = rt->rtsp_streams[i];
1576 1576
             if (rtsp_st->rtp_handle) {
1577
-                fd = url_get_file_handle(rtsp_st->rtp_handle);
1578
-                fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
1579
-                if (FFMAX(fd, fd_rtcp) > fd_max)
1580
-                    fd_max = FFMAX(fd, fd_rtcp);
1581
-                FD_SET(fd, &rfds);
1582
-                FD_SET(fd_rtcp, &rfds);
1577
+                p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle);
1578
+                p[max_p++].events = POLLIN;
1579
+                p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
1580
+                p[max_p++].events = POLLIN;
1583 1581
             }
1584 1582
         }
1585
-        tv.tv_sec = 0;
1586
-        tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
1587
-        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
1583
+        n = poll(p, max_p, POLL_TIMEOUT_MS);
1588 1584
         if (n > 0) {
1585
+            int j = 1 - (tcp_fd == -1);
1589 1586
             timeout_cnt = 0;
1590 1587
             for (i = 0; i < rt->nb_rtsp_streams; i++) {
1591 1588
                 rtsp_st = rt->rtsp_streams[i];
1592 1589
                 if (rtsp_st->rtp_handle) {
1593
-                    fd = url_get_file_handle(rtsp_st->rtp_handle);
1594
-                    fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
1595
-                    if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) {
1590
+                    if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
1596 1591
                         ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
1597 1592
                         if (ret > 0) {
1598 1593
                             *prtsp_st = rtsp_st;
1599 1594
                             return ret;
1600 1595
                         }
1601 1596
                     }
1597
+                    j+=2;
1602 1598
                 }
1603 1599
             }
1604 1600
 #if CONFIG_RTSP_DEMUXER
1605
-            if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
1601
+            if (tcp_fd != -1 && p[0].revents & POLLIN) {
1606 1602
                 RTSPMessageHeader reply;
1607 1603
 
1608 1604
                 ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
... ...
@@ -326,6 +326,11 @@ typedef struct RTSPState {
326 326
      * The number of returned packets
327 327
      */
328 328
     uint64_t packets;
329
+
330
+    /**
331
+     * Polling array for udp
332
+     */
333
+    struct pollfd *p;
329 334
 } RTSPState;
330 335
 
331 336
 /**
... ...
@@ -22,8 +22,8 @@
22 22
 #include "avformat.h"
23 23
 
24 24
 #include <sys/time.h>
25
-#if HAVE_SYS_SELECT_H
26
-#include <sys/select.h>
25
+#if HAVE_POLL_H
26
+#include <poll.h>
27 27
 #endif
28 28
 #include "network.h"
29 29
 #include "rtsp.h"
... ...
@@ -172,23 +172,16 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt)
172 172
 {
173 173
     RTSPState *rt = s->priv_data;
174 174
     RTSPStream *rtsp_st;
175
-    fd_set rfds;
176
-    int n, tcp_fd;
177
-    struct timeval tv;
175
+    int n;
176
+    struct pollfd p = {url_get_file_handle(rt->rtsp_hd), POLLIN, 0};
178 177
     AVFormatContext *rtpctx;
179 178
     int ret;
180 179
 
181
-    tcp_fd = url_get_file_handle(rt->rtsp_hd);
182
-
183 180
     while (1) {
184
-        FD_ZERO(&rfds);
185
-        FD_SET(tcp_fd, &rfds);
186
-        tv.tv_sec = 0;
187
-        tv.tv_usec = 0;
188
-        n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv);
181
+        n = poll(&p, 1, 0);
189 182
         if (n <= 0)
190 183
             break;
191
-        if (FD_ISSET(tcp_fd, &rfds)) {
184
+        if (p.revents & POLLIN) {
192 185
             RTSPMessageHeader reply;
193 186
 
194 187
             /* Don't let ff_rtsp_read_reply handle interleaved packets,
... ...
@@ -25,8 +25,8 @@
25 25
 #include "network.h"
26 26
 #include "os_support.h"
27 27
 #include "internal.h"
28
-#if HAVE_SYS_SELECT_H
29
-#include <sys/select.h>
28
+#if HAVE_POLL_H
29
+#include <poll.h>
30 30
 #endif
31 31
 #include <sys/time.h>
32 32
 
... ...
@@ -183,19 +183,15 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
183 183
     struct SAPState *sap = s->priv_data;
184 184
     int fd = url_get_file_handle(sap->ann_fd);
185 185
     int n, ret;
186
-    fd_set rfds;
187
-    struct timeval tv;
186
+    struct pollfd p = {fd, POLLIN, 0};
188 187
     uint8_t recvbuf[1500];
189 188
 
190 189
     if (sap->eof)
191 190
         return AVERROR_EOF;
192 191
 
193 192
     while (1) {
194
-        FD_ZERO(&rfds);
195
-        FD_SET(fd, &rfds);
196
-        tv.tv_sec = tv.tv_usec = 0;
197
-        n = select(fd + 1, &rfds, NULL, NULL, &tv);
198
-        if (n <= 0 || !FD_ISSET(fd, &rfds))
193
+        n = poll(&p, 1, 0);
194
+        if (n <= 0 || !(p.revents & POLLIN))
199 195
             break;
200 196
         ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
201 197
         if (ret >= 8) {
... ...
@@ -23,8 +23,8 @@
23 23
 #include "internal.h"
24 24
 #include "network.h"
25 25
 #include "os_support.h"
26
-#if HAVE_SYS_SELECT_H
27
-#include <sys/select.h>
26
+#if HAVE_POLL_H
27
+#include <poll.h>
28 28
 #endif
29 29
 #include <sys/time.h>
30 30
 
... ...
@@ -38,9 +38,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
38 38
     struct addrinfo hints, *ai, *cur_ai;
39 39
     int port, fd = -1;
40 40
     TCPContext *s = NULL;
41
-    fd_set wfds, efds;
42
-    int fd_max, ret;
43
-    struct timeval tv;
41
+    int ret;
44 42
     socklen_t optlen;
45 43
     char hostname[1024],proto[1024],path[1024];
46 44
     char portstr[10];
... ...
@@ -73,6 +71,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
73 73
  redo:
74 74
     ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
75 75
     if (ret < 0) {
76
+        struct pollfd p = {fd, POLLOUT, 0};
76 77
         if (ff_neterrno() == FF_NETERROR(EINTR)) {
77 78
             if (url_interrupt_cb())
78 79
                 goto fail1;
... ...
@@ -88,15 +87,8 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
88 88
                 ret = AVERROR(EINTR);
89 89
                 goto fail1;
90 90
             }
91
-            fd_max = fd;
92
-            FD_ZERO(&wfds);
93
-            FD_ZERO(&efds);
94
-            FD_SET(fd, &wfds);
95
-            FD_SET(fd, &efds);
96
-            tv.tv_sec = 0;
97
-            tv.tv_usec = 100 * 1000;
98
-            ret = select(fd_max + 1, NULL, &wfds, &efds, &tv);
99
-            if (ret > 0 && (FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds)))
91
+            ret = poll(&p, 1, 100);
92
+            if (ret > 0)
100 93
                 break;
101 94
         }
102 95
 
... ...
@@ -140,20 +132,14 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
140 140
 static int tcp_read(URLContext *h, uint8_t *buf, int size)
141 141
 {
142 142
     TCPContext *s = h->priv_data;
143
-    int len, fd_max, ret;
144
-    fd_set rfds;
145
-    struct timeval tv;
143
+    struct pollfd p = {s->fd, POLLIN, 0};
144
+    int len, ret;
146 145
 
147 146
     for (;;) {
148 147
         if (url_interrupt_cb())
149 148
             return AVERROR(EINTR);
150
-        fd_max = s->fd;
151
-        FD_ZERO(&rfds);
152
-        FD_SET(s->fd, &rfds);
153
-        tv.tv_sec = 0;
154
-        tv.tv_usec = 100 * 1000;
155
-        ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
156
-        if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
149
+        ret = poll(&p, 1, 100);
150
+        if (ret == 1 && p.revents & POLLIN) {
157 151
             len = recv(s->fd, buf, size, 0);
158 152
             if (len < 0) {
159 153
                 if (ff_neterrno() != FF_NETERROR(EINTR) &&
... ...
@@ -171,21 +157,15 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size)
171 171
 static int tcp_write(URLContext *h, const uint8_t *buf, int size)
172 172
 {
173 173
     TCPContext *s = h->priv_data;
174
-    int ret, size1, fd_max, len;
175
-    fd_set wfds;
176
-    struct timeval tv;
174
+    int ret, size1, len;
175
+    struct pollfd p = {s->fd, POLLOUT, 0};
177 176
 
178 177
     size1 = size;
179 178
     while (size > 0) {
180 179
         if (url_interrupt_cb())
181 180
             return AVERROR(EINTR);
182
-        fd_max = s->fd;
183
-        FD_ZERO(&wfds);
184
-        FD_SET(s->fd, &wfds);
185
-        tv.tv_sec = 0;
186
-        tv.tv_usec = 100 * 1000;
187
-        ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
188
-        if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
181
+        ret = poll(&p, 1, 100);
182
+        if (ret == 1 && p.revents & POLLOUT) {
189 183
             len = send(s->fd, buf, size, 0);
190 184
             if (len < 0) {
191 185
                 if (ff_neterrno() != FF_NETERROR(EINTR) &&
... ...
@@ -31,8 +31,8 @@
31 31
 #include "internal.h"
32 32
 #include "network.h"
33 33
 #include "os_support.h"
34
-#if HAVE_SYS_SELECT_H
35
-#include <sys/select.h>
34
+#if HAVE_POLL_H
35
+#include <poll.h>
36 36
 #endif
37 37
 #include <sys/time.h>
38 38
 
... ...
@@ -432,25 +432,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
432 432
 static int udp_read(URLContext *h, uint8_t *buf, int size)
433 433
 {
434 434
     UDPContext *s = h->priv_data;
435
+    struct pollfd p = {s->udp_fd, POLLIN, 0};
435 436
     int len;
436
-    fd_set rfds;
437 437
     int ret;
438
-    struct timeval tv;
439 438
 
440 439
     for(;;) {
441 440
         if (url_interrupt_cb())
442 441
             return AVERROR(EINTR);
443
-        FD_ZERO(&rfds);
444
-        FD_SET(s->udp_fd, &rfds);
445
-        tv.tv_sec = 0;
446
-        tv.tv_usec = 100 * 1000;
447
-        ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv);
442
+        ret = poll(&p, 1, 100);
448 443
         if (ret < 0) {
449 444
             if (ff_neterrno() == FF_NETERROR(EINTR))
450 445
                 continue;
451 446
             return AVERROR(EIO);
452 447
         }
453
-        if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds)))
448
+        if (!(ret == 1 && p.revents & POLLIN))
454 449
             continue;
455 450
         len = recv(s->udp_fd, buf, size, 0);
456 451
         if (len < 0) {