All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.