* [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected
@ 2018-08-30 15:57 Gavin Grant
2018-08-30 15:57 ` Gavin Grant
0 siblings, 1 reply; 4+ messages in thread
From: Gavin Grant @ 2018-08-30 15:57 UTC (permalink / raw)
To: samuel.thibault, jan.kiszka, qemu-devel
[PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected
Please bear with me, since this is my first correspondence with the qemu-devel
mailing list (or any public devel mailing list for that matter!).
I believe I have witnessed a discrepancy between SLIRP TCP and normal UNIX/Linux
TCP behaviour relating to the sending of RST packet(s) after a socket has been
closed gracefully by a host client application, then the application
subsequently exits. When the host socket is closed gracefully, it is in a
"half-closed" state. i.e. The socket can no longer be read from, but it can be
written to and will wait in FIN_WAIT_1 & FIN_WAIT_2 states until the remote peer
sends a FIN. This is fine. But when the application exits, the host socket is no
longer connected. I would expect subsequent slirp_send() calls to return an EPIPE
error, causing RST packet(s) to be sent to the server, causing it to close its
socket.
However, unlike soread() in 27d92ebc5ed1bb0b518d0ebc4c609182ad20a799, sowrite()
does not call tcp_drop() for specific errno's, so the server socket will remain
open. sbappend() does not implement error handling, as it relies on errors to
be handled in soread().
My proposed patch attempts to address this by checking for closed & disconnected
socket status in soread(). Forgive me if my logic and proposal are foolish!
The application(s) that I observed this behaviour from were libiio test
programs (https://github.com/analogdevicesinc/libiio/tree/master/tests), which
connect to an iiod daemon process running on the server, to interface with the
Linux Industrial Input/Output (IIO) subsystem. I noticed that if iiod is running
on a QEMU server with SLIRP, then iiod does not notice when client applications
close their connection and exit. This can result in multiple threads open on the
server, with their sockets stuck in the CLOSE_WAIT state. Once several of these
threads exist, my QEMU system becomes extremely slow and unusable.
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected
2018-08-30 15:57 [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected Gavin Grant
@ 2018-08-30 15:57 ` Gavin Grant
2018-08-30 16:02 ` Samuel Thibault
2018-10-07 17:52 ` Samuel Thibault
0 siblings, 2 replies; 4+ messages in thread
From: Gavin Grant @ 2018-08-30 15:57 UTC (permalink / raw)
To: samuel.thibault, jan.kiszka, qemu-devel; +Cc: Gavin Grant
Commit 27d92ebc5ed1bb0b518d0ebc4c609182ad20a799 handled the case where the TCP
connection is abruptly closed via a RST packet, by checking for the ECONNRESET
errno. However it does not consider the case where the connection has been
half-closed by the host (FIN/ACK), then the host socket is disconnected. For
example, if the host application calls close() on the socket, then the
application exits.
In this case, the socket still exists due to the file descriptor in SLIRP, but
it is disconnected. recv() does not indicate an error since an orderly socket
close has previously occurred. The socket will then be stuck in FIN_WAIT_2,
until the peer sends FIN/ACK or a timeout occurs. Instead we can send a RST
to the peer and transition to the CLOSED state.
Signed-off-by: Gavin Grant <gavingrant@protonmail.com>
---
slirp/socket.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/slirp/socket.c b/slirp/socket.c
index 08fe98907d..543bd5feaf 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -204,12 +204,17 @@ soread(struct socket *so)
return 0;
else {
int err;
+ struct sockaddr addr;
socklen_t slen = sizeof err;
err = errno;
if (nn == 0) {
- getsockopt(so->s, SOL_SOCKET, SO_ERROR,
- &err, &slen);
+ if (getpeername(so->s, &addr, &slen) < 0) {
+ err = errno;
+ } else {
+ getsockopt(so->s, SOL_SOCKET, SO_ERROR,
+ &err, &slen);
+ }
}
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
--
2.11.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected
2018-08-30 15:57 ` Gavin Grant
@ 2018-08-30 16:02 ` Samuel Thibault
2018-10-07 17:52 ` Samuel Thibault
1 sibling, 0 replies; 4+ messages in thread
From: Samuel Thibault @ 2018-08-30 16:02 UTC (permalink / raw)
To: Gavin Grant; +Cc: jan.kiszka, qemu-devel
Hello,
The principle seems sane, I'll have a look.
Thanks,
Samuel
Gavin Grant, le jeu. 30 août 2018 16:57:57 +0100, a ecrit:
> Commit 27d92ebc5ed1bb0b518d0ebc4c609182ad20a799 handled the case where the TCP
> connection is abruptly closed via a RST packet, by checking for the ECONNRESET
> errno. However it does not consider the case where the connection has been
> half-closed by the host (FIN/ACK), then the host socket is disconnected. For
> example, if the host application calls close() on the socket, then the
> application exits.
>
> In this case, the socket still exists due to the file descriptor in SLIRP, but
> it is disconnected. recv() does not indicate an error since an orderly socket
> close has previously occurred. The socket will then be stuck in FIN_WAIT_2,
> until the peer sends FIN/ACK or a timeout occurs. Instead we can send a RST
> to the peer and transition to the CLOSED state.
>
> Signed-off-by: Gavin Grant <gavingrant@protonmail.com>
> ---
> slirp/socket.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/slirp/socket.c b/slirp/socket.c
> index 08fe98907d..543bd5feaf 100644
> --- a/slirp/socket.c
> +++ b/slirp/socket.c
> @@ -204,12 +204,17 @@ soread(struct socket *so)
> return 0;
> else {
> int err;
> + struct sockaddr addr;
> socklen_t slen = sizeof err;
>
> err = errno;
> if (nn == 0) {
> - getsockopt(so->s, SOL_SOCKET, SO_ERROR,
> - &err, &slen);
> + if (getpeername(so->s, &addr, &slen) < 0) {
> + err = errno;
> + } else {
> + getsockopt(so->s, SOL_SOCKET, SO_ERROR,
> + &err, &slen);
> + }
> }
>
> DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
> --
> 2.11.0
>
--
Samuel
***e trouve un .xls
***e passe un moment à se demander quelle version de xml c'est ça, le .xls
e: donc j'ai fait un file....
-+- #sos - on n'a pas forcément les mêmes références que tout le monde -+-
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected
2018-08-30 15:57 ` Gavin Grant
2018-08-30 16:02 ` Samuel Thibault
@ 2018-10-07 17:52 ` Samuel Thibault
1 sibling, 0 replies; 4+ messages in thread
From: Samuel Thibault @ 2018-10-07 17:52 UTC (permalink / raw)
To: Gavin Grant; +Cc: jan.kiszka, qemu-devel
Hello,
Gavin Grant, le jeu. 30 août 2018 16:57:57 +0100, a ecrit:
> Commit 27d92ebc5ed1bb0b518d0ebc4c609182ad20a799 handled the case where the TCP
> connection is abruptly closed via a RST packet, by checking for the ECONNRESET
> errno. However it does not consider the case where the connection has been
> half-closed by the host (FIN/ACK), then the host socket is disconnected. For
> example, if the host application calls close() on the socket, then the
> application exits.
>
> In this case, the socket still exists due to the file descriptor in SLIRP, but
> it is disconnected. recv() does not indicate an error since an orderly socket
> close has previously occurred. The socket will then be stuck in FIN_WAIT_2,
> until the peer sends FIN/ACK or a timeout occurs. Instead we can send a RST
> to the peer and transition to the CLOSED state.
>
> Signed-off-by: Gavin Grant <gavingrant@protonmail.com>
I have fixed it a bit and pushed to my tree, thanks!
Samuel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-10-07 17:52 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-30 15:57 [Qemu-devel] [PATCH] slirp: Propagate host TCP RST packet to the guest after socket disconnected Gavin Grant
2018-08-30 15:57 ` Gavin Grant
2018-08-30 16:02 ` Samuel Thibault
2018-10-07 17:52 ` Samuel Thibault
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).