* [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom.
@ 2019-02-28 11:59 llyzs
2019-02-28 20:51 ` Samuel Thibault
0 siblings, 1 reply; 5+ messages in thread
From: llyzs @ 2019-02-28 11:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Samuel Thibault, Jan Kiszka, Marc-André Lureau
Sometimes sorecvfrom() is called from slirp.c because revents == G_IO_IN,
however inside sorecvfrom() function, ioctlsocket() returns 0 bytes available
and recvfrom could be blocking indefinitely. This adds a non-blocking flag to
recvfrom and checks data availability.
---
slirp/socket.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/slirp/socket.c b/slirp/socket.c
index c01d8696af..ea30478ce6 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -581,7 +581,7 @@ sorecvfrom(struct socket *so)
}
/* } */
- m->m_len = recvfrom(so->s, m->m_data, len, 0,
+ m->m_len = recvfrom(so->s, m->m_data, len, MSG_DONTWAIT,
(struct sockaddr *)&addr, &addrlen);
DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
m->m_len, errno,strerror(errno)));
@@ -618,6 +618,8 @@ sorecvfrom(struct socket *so)
break;
}
m_free(m);
+ } else if (m->m_len==0) {
+ m_free(m);
} else {
/*
* Hack: domain name lookup will be used the most for UDP,
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom.
2019-02-28 11:59 [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom llyzs
@ 2019-02-28 20:51 ` Samuel Thibault
2019-03-01 4:27 ` llyzs
0 siblings, 1 reply; 5+ messages in thread
From: Samuel Thibault @ 2019-02-28 20:51 UTC (permalink / raw)
To: llyzs; +Cc: qemu-devel, Jan Kiszka, Marc-André Lureau
Hello,
llyzs, le jeu. 28 févr. 2019 19:59:12 +0800, a ecrit:
> Sometimes sorecvfrom() is called from slirp.c because revents == G_IO_IN,
> however inside sorecvfrom() function, ioctlsocket() returns 0 bytes available
> and recvfrom could be blocking indefinitely. This adds a non-blocking flag to
> recvfrom and checks data availability.
When ioctlsocket() returns 0 bytes available, we could as well just
immediately return, without even calling recvfrom. We could just move
that ioctlsocket call above the m_get() call, so we can just return
without having to clean up anything.
This however still looks weird. AFAIK, G_IO_IN means that we can make
one recv call and be sure that it won't block. Do you have an idea why
it wouldn't necessarily be the case?
Samuel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom.
2019-02-28 20:51 ` Samuel Thibault
@ 2019-03-01 4:27 ` llyzs
2019-03-01 5:12 ` Samuel Thibault
2019-03-01 5:13 ` [Qemu-devel] [PATCHv2] slirp: check for ioctlsocket error and 0-length udp payload llyzs
0 siblings, 2 replies; 5+ messages in thread
From: llyzs @ 2019-03-01 4:27 UTC (permalink / raw)
To: Samuel Thibault; +Cc: qemu-devel, Jan Kiszka, Marc-André Lureau
Hi,
I believe this is because UDP packet can have 0 length payload. I
quote some resources here:
https://stackoverflow.com/questions/12505892/under-linux-can-recv-ever-return-0-on-udp
https://stackoverflow.com/questions/5307031/how-to-detect-receipt-of-a-0-length-udp-datagram
I also found out that sometimes ioctlsocket() call can return error
(probably caused by my unstable wifi linux driver), in which case we
can also return immediately.
I will submit a new version of the patch according to your suggestions.
On Fri, 1 Mar 2019 at 04:51, Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Hello,
>
> llyzs, le jeu. 28 févr. 2019 19:59:12 +0800, a ecrit:
> > Sometimes sorecvfrom() is called from slirp.c because revents == G_IO_IN,
> > however inside sorecvfrom() function, ioctlsocket() returns 0 bytes available
> > and recvfrom could be blocking indefinitely. This adds a non-blocking flag to
> > recvfrom and checks data availability.
>
> When ioctlsocket() returns 0 bytes available, we could as well just
> immediately return, without even calling recvfrom. We could just move
> that ioctlsocket call above the m_get() call, so we can just return
> without having to clean up anything.
>
> This however still looks weird. AFAIK, G_IO_IN means that we can make
> one recv call and be sure that it won't block. Do you have an idea why
> it wouldn't necessarily be the case?
>
> Samuel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom.
2019-03-01 4:27 ` llyzs
@ 2019-03-01 5:12 ` Samuel Thibault
2019-03-01 5:13 ` [Qemu-devel] [PATCHv2] slirp: check for ioctlsocket error and 0-length udp payload llyzs
1 sibling, 0 replies; 5+ messages in thread
From: Samuel Thibault @ 2019-03-01 5:12 UTC (permalink / raw)
To: llyzs; +Cc: qemu-devel, Jan Kiszka, Marc-André Lureau
llyzs, le ven. 01 mars 2019 12:27:31 +0800, a ecrit:
> I believe this is because UDP packet can have 0 length payload.
Ah, right, that one makes sense indeed.
> I also found out that sometimes ioctlsocket() call can return error
> (probably caused by my unstable wifi linux driver), in which case we
> can also return immediately.
We should check for the value returned by ioctlsocket() then, otherwise
the value of n is undefined.
Samuel
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCHv2] slirp: check for ioctlsocket error and 0-length udp payload.
2019-03-01 4:27 ` llyzs
2019-03-01 5:12 ` Samuel Thibault
@ 2019-03-01 5:13 ` llyzs
1 sibling, 0 replies; 5+ messages in thread
From: llyzs @ 2019-03-01 5:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Jan Kiszka, Marc-André Lureau, Samuel Thibault
Sometimes sorecvfrom() is called from slirp.c because revents == G_IO_IN,
but there is 0 bytes available and recvfrom could be blocking indefinitely.
This is likely due to 0-length udp payload. This also adds an error
checking for ioctlsocket.
Signed-off-by: Vic Lee <llyzs.vic@gmail.com>
---
slirp/socket.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/slirp/socket.c b/slirp/socket.c
index c01d8696af..a624d829e3 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -549,6 +549,15 @@ sorecvfrom(struct socket *so)
int n;
#endif
+ if (ioctlsocket(so->s, FIONREAD, &n) != 0) {
+ DEBUG_MISC((dfd," ioctlsocket errno = %d-%s\n",
+ errno,strerror(errno)));
+ return;
+ }
+ if (n == 0) {
+ return;
+ }
+
m = m_get(so->slirp);
if (!m) {
return;
@@ -572,7 +581,6 @@ sorecvfrom(struct socket *so)
*/
len = M_FREEROOM(m);
/* if (so->so_fport != htons(53)) { */
- ioctlsocket(so->s, FIONREAD, &n);
if (n > len) {
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-03-01 5:13 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-28 11:59 [Qemu-devel] [PATCH] socket: fix blocking udp recvfrom llyzs
2019-02-28 20:51 ` Samuel Thibault
2019-03-01 4:27 ` llyzs
2019-03-01 5:12 ` Samuel Thibault
2019-03-01 5:13 ` [Qemu-devel] [PATCHv2] slirp: check for ioctlsocket error and 0-length udp payload llyzs
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).