Browse code

os: replace select with poll

Select has limitations on the fd values it could accept and silently
breaks when it is reached.
(cherry picked from commit a8475bbdb64e638bd8161df9647876fd23f8a29a)

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) {