Commit 4c60d7c5 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Switch net_Write to poll() to avoid fd set overflow.

parent a4e6865c
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#ifdef HAVE_POLL #ifdef HAVE_POLL
# include <sys/poll.h> # include <poll.h>
#endif #endif
#include "network.h" #include "network.h"
...@@ -140,7 +140,7 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv, ...@@ -140,7 +140,7 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
uint8_t *restrict buf, size_t buflen, uint8_t *restrict buf, size_t buflen,
int wait_ms, vlc_bool_t waitall ) int wait_ms, vlc_bool_t waitall )
{ {
int total = 0, n; int total = 0;
do do
{ {
...@@ -164,7 +164,7 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv, ...@@ -164,7 +164,7 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
if (p_this->b_die) if (p_this->b_die)
return total; return total;
n = poll (ufd, fdc, (wait_ms == -1) ? -1 : delay_ms); int n = poll (ufd, fdc, (wait_ms == -1) ? -1 : delay_ms);
if (n == -1) if (n == -1)
goto error; goto error;
...@@ -199,9 +199,9 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv, ...@@ -199,9 +199,9 @@ net_ReadInner( vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
maxfd = fdv[i]; maxfd = fdv[i];
} }
n = select (maxfd + 1, &set, NULL, NULL, int n = select (maxfd + 1, &set, NULL, NULL,
(wait_ms == -1) ? NULL (wait_ms == -1) ? NULL
: &(struct timeval){ 0, delay_ms * 1000 }); : &(struct timeval){ 0, delay_ms * 1000 });
if (n == -1) if (n == -1)
goto error; goto error;
...@@ -242,7 +242,7 @@ receive: ...@@ -242,7 +242,7 @@ receive:
/* On Win32, recv() fails if the datagram doesn't fit inside /* On Win32, recv() fails if the datagram doesn't fit inside
* the passed buffer, even though the buffer will be filled * the passed buffer, even though the buffer will be filled
* with the first part of the datagram. */ * with the first part of the datagram. */
msg_Err( p_this, "recv() failed. " msg_Err( p_this, "Receive error: "
"Increase the mtu size (--mtu option)" ); "Increase the mtu size (--mtu option)" );
total += buflen; total += buflen;
return total; return total;
...@@ -271,8 +271,8 @@ receive: ...@@ -271,8 +271,8 @@ receive:
return total; // timeout return total; // timeout
error: error:
msg_Err (p_this, "Receive error: %s", net_strerror (net_errno)); msg_Err (p_this, "Read error: %s", net_strerror (net_errno));
return (total > 0) ? total : -1; return total ?: -1;
} }
...@@ -337,56 +337,70 @@ int __net_Select( vlc_object_t *restrict p_this, const int *restrict pi_fd, ...@@ -337,56 +337,70 @@ int __net_Select( vlc_object_t *restrict p_this, const int *restrict pi_fd,
int __net_Write( vlc_object_t *p_this, int fd, const v_socket_t *p_vs, int __net_Write( vlc_object_t *p_this, int fd, const v_socket_t *p_vs,
const uint8_t *p_data, int i_data ) const uint8_t *p_data, int i_data )
{ {
struct timeval timeout; int i_total = 0;
fd_set fds_w, fds_e;
int i_send;
int i_total = 0;
int i_ret;
vlc_bool_t b_die = p_this->b_die; while (i_data > 0)
while( i_data > 0 )
{ {
do if (p_this->b_die)
{ return i_total;
if( p_this->b_die != b_die )
{
return 0;
}
/* Initialize file descriptor set */
FD_ZERO( &fds_w );
FD_SET( fd, &fds_w );
FD_ZERO( &fds_e );
FD_SET( fd, &fds_e );
/* We'll wait 0.5 second if nothing happens */ #ifdef HAVE_POLL
timeout.tv_sec = 0; struct pollfd ufd[1];
timeout.tv_usec = 500000; memset (ufd, 0, sizeof (ufd));
ufd[0].fd = fd;
ufd[0].events = POLLOUT;
} while( (i_ret = select(fd + 1, NULL, &fds_w, &fds_e, &timeout)) == 0 int val = poll (ufd, 1, 500);
|| ( i_ret < 0 && errno == EINTR ) ); #else
fd_set set;
FD_ZERO (&set);
if( i_ret < 0 ) #if !defined(WIN32) && !defined(UNDER_CE)
if (fd >= FD_SETSIZE)
{ {
msg_Err( p_this, "network error: %s", net_strerror(net_errno) ); /* We don't want to overflow select() fd_set */
return i_total > 0 ? i_total : -1; msg_Err (p_this, "select set overflow");
return -1;
} }
#endif
FD_SET (fd, &set);
if( ( i_send = (p_vs != NULL) int val = select (fd + 1, NULL, &set, NULL,
? p_vs->pf_send( p_vs->p_sys, p_data, i_data ) &(struct timeval){ 0, 500000 });
: send( fd, p_data, i_data, 0 ) ) < 0 ) #endif
switch (val)
{ {
/* XXX With udp for example, it will issue a message if the host case -1:
* isn't listening */ if (errno != EINTR)
/* msg_Err( p_this, "send failed (%s)", strerror(errno) ); */ {
return i_total > 0 ? i_total : -1; msg_Err (p_this, "Write error: %s",
net_strerror (net_errno));
return i_total ?: -1;
}
case 0:
continue;
} }
p_data += i_send; if (p_vs != NULL)
i_data -= i_send; val = p_vs->pf_send (p_vs->p_sys, p_data, i_data);
i_total+= i_send; else
#if defined(WIN32) || defined(UNDER_CE)
val = recv (fd, p_data, i_data, 0);
#else
val = write (fd, p_data, i_data);
#endif
if (val == -1)
return i_total ?: -1;
if (val == 0)
return i_total;
p_data += val;
i_data -= val;
i_total += val;
} }
return i_total; return i_total;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment