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

Remove potential deadlocks in waitpipe with net_*

parent d9b51113
...@@ -555,25 +555,25 @@ int __vlc_object_waitpipe( vlc_object_t *obj ) ...@@ -555,25 +555,25 @@ int __vlc_object_waitpipe( vlc_object_t *obj )
vlc_spin_lock (&internals->spin); vlc_spin_lock (&internals->spin);
signaled = internals->b_signaled; signaled = internals->b_signaled;
if ((!signaled) && (internals->pipes[0] == -1)) if (internals->pipes[0] == -1)
{ {
internals->pipes[0] = pfd[0]; internals->pipes[0] = pfd[0];
internals->pipes[1] = pfd[1]; internals->pipes[1] = pfd[1];
} }
else
race = VLC_TRUE;
} }
vlc_spin_unlock (&internals->spin); vlc_spin_unlock (&internals->spin);
if (race || signaled) if (race)
{ { /* Race condition: two threads call pipe() - unlikely */
close (pfd[0]); close (pfd[0]);
close (pfd[1]); close (pfd[1]);
}
if (signaled) if (signaled)
{ /* vlc_object_signal() was already invoked! */ /* Race condition: lc_object_signal() already invoked! */
errno = EINTR; while (write (internals->pipes[1], &(char){ 0 }, 1) < 0);
return -1;
}
}
return internals->pipes[0]; return internals->pipes[0];
} }
......
...@@ -258,7 +258,8 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host, ...@@ -258,7 +258,8 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
***************************************************************************** *****************************************************************************
* Reads from a network socket. * Reads from a network socket.
* If waitall is true, then we repeat until we have read the right amount of * If waitall is true, then we repeat until we have read the right amount of
* data; in that case, a short count means EOF has been reached. * data; in that case, a short count means EOF has been reached or the VLC
* object has been signaled.
*****************************************************************************/ *****************************************************************************/
ssize_t ssize_t
__net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs, __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs,
...@@ -270,27 +271,17 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs, ...@@ -270,27 +271,17 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs,
{ .fd = -1, .events = POLLIN }, { .fd = -1, .events = POLLIN },
}; };
vlc_object_lock (p_this);
ufd[1].fd = vlc_object_waitpipe (p_this);
while (i_buflen > 0) while (i_buflen > 0)
{ {
int val; int val;
if (!vlc_object_alive (p_this)) ufd[1].fd = vlc_object_waitpipe (p_this);
if (ufd[1].fd == -1)
{ {
#if defined(WIN32) || defined(UNDER_CE)
WSASetLastError (WSAEINTR);
#else
errno = EINTR;
#endif
goto error;
} }
ufd[0].revents = ufd[1].revents = 0; ufd[0].revents = ufd[1].revents = 0;
vlc_object_unlock (p_this);
val = poll (ufd, sizeof (ufd) / sizeof (ufd[0]), -1); val = poll (ufd, sizeof (ufd) / sizeof (ufd[0]), -1);
vlc_object_lock (p_this);
if (val < 0) if (val < 0)
goto error; goto error;
...@@ -298,9 +289,16 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs, ...@@ -298,9 +289,16 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs,
if (ufd[1].revents) if (ufd[1].revents)
{ {
msg_Dbg (p_this, "socket %d polling interrupted", fd); msg_Dbg (p_this, "socket %d polling interrupted", fd);
vlc_object_wait (p_this); if (i_total == 0)
msg_Dbg (p_this, "socket %d polling restarting", fd); {
continue; #if defined(WIN32) || defined(UNDER_CE)
WSASetLastError (WSAEINTR);
#else
errno = EINTR;
#endif
goto error;
}
break;
} }
assert (ufd[0].revents); assert (ufd[0].revents);
...@@ -378,13 +376,10 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs, ...@@ -378,13 +376,10 @@ __net_Read (vlc_object_t *restrict p_this, int fd, const v_socket_t *vs,
break; break;
} }
vlc_object_unlock (p_this);
return i_total; return i_total;
error: error:
msg_Err (p_this, "Read error: %m"); msg_Err (p_this, "Read error: %m");
vlc_object_unlock (p_this);
return -1; return -1;
} }
......
...@@ -286,10 +286,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait ) ...@@ -286,10 +286,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
assert( pi_fd != NULL ); assert( pi_fd != NULL );
vlc_object_lock (p_this);
evfd = vlc_object_waitpipe (p_this); evfd = vlc_object_waitpipe (p_this);
while (vlc_object_alive (p_this)) for (;;)
{ {
unsigned n = 0; unsigned n = 0;
while (pi_fd[n] != -1) while (pi_fd[n] != -1)
...@@ -303,8 +302,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait ) ...@@ -303,8 +302,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
ufd[i].events = POLLIN; ufd[i].events = POLLIN;
ufd[i].revents = 0; ufd[i].revents = 0;
} }
if (evfd == -1)
n--; /* avoid EBADF */
vlc_object_unlock (p_this);
switch (poll (ufd, n, timeout)) switch (poll (ufd, n, timeout))
{ {
case -1: case -1:
...@@ -313,11 +313,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait ) ...@@ -313,11 +313,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
case 0: case 0:
return -1; /* NOTE: p_this already unlocked */ return -1; /* NOTE: p_this already unlocked */
} }
vlc_object_lock (p_this);
if (ufd[n].revents) if (ufd[n].revents)
{ {
vlc_object_wait (p_this);
errno = EINTR; errno = EINTR;
break; break;
} }
...@@ -338,11 +336,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait ) ...@@ -338,11 +336,9 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
*/ */
memmove (pi_fd + i, pi_fd + i + 1, n - (i + 1)); memmove (pi_fd + i, pi_fd + i + 1, n - (i + 1));
pi_fd[n - 1] = sfd; pi_fd[n - 1] = sfd;
vlc_object_unlock (p_this);
return fd; return fd;
} }
} }
vlc_object_unlock (p_this);
return -1; return -1;
} }
......
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