diff options
author | John Levon <john.levon@nutanix.com> | 2021-04-06 15:26:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-06 15:26:19 +0100 |
commit | 996d4f3cdae229fee9b5c8867d87beeb9172b97f (patch) | |
tree | 099dc048724bb0d895c2bbc886e8e0448ab35dc0 /lib/tran_sock.c | |
parent | e97a5e8c911acd8826542b1de30fb834901f4e76 (diff) | |
download | libvfio-user-996d4f3cdae229fee9b5c8867d87beeb9172b97f.zip libvfio-user-996d4f3cdae229fee9b5c8867d87beeb9172b97f.tar.gz libvfio-user-996d4f3cdae229fee9b5c8867d87beeb9172b97f.tar.bz2 |
implement short read/write, EOF handling (#415)
Report any short reads to callers as ECONNRESET, which is the closest we can
meaningfully get right now. This also fixes get_next_command(), which previously
wasn't checking for short reads at all.
When we fail to send or recv from the socket due to the client disappearing in
some manner, call into vfu_reset_ctx() to clean up the connection fd, allowing a
subsequent vfu_attach_ctx() to work.
If we get 0 bytes from recv[msg](), this is reported by the transport as ENOMSG,
and is a normal EOF condition.
We can also get ECONNRESET: this can happen when we've written unacknowledged
data to the socket, the client side socket is closed, and we try a subsequent
read.
Finally, we can get a short read or write. Our handling of these still has
issues, but for now we'll presume this means the client has gone too. It may
in fact be due to a client bug - if it failed to write enough data - but right
now, we can't easily tell that.
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'lib/tran_sock.c')
-rw-r--r-- | lib/tran_sock.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/lib/tran_sock.c b/lib/tran_sock.c index 9a58570..ea01a68 100644 --- a/lib/tran_sock.c +++ b/lib/tran_sock.c @@ -173,6 +173,8 @@ get_msg(void *data, size_t len, int *fds, size_t *nr_fds, int sock_fd, return -errno; } else if (ret == 0) { return -ENOMSG; + } else if ((size_t)ret < len) { + return -ECONNRESET; } if (msg.msg_flags & MSG_CTRUNC || msg.msg_flags & MSG_TRUNC) { @@ -222,9 +224,6 @@ tran_sock_recv_fds(int sock, struct vfio_user_header *hdr, bool is_reply, if (ret < 0) { return ret; } - if (ret < (int)sizeof(*hdr)) { - return -EINVAL; - } if (is_reply) { if (msg_id != NULL && hdr->msg_id != *msg_id) { @@ -257,11 +256,12 @@ tran_sock_recv_fds(int sock, struct vfio_user_header *hdr, bool is_reply, return -errno; } else if (ret == 0) { return -ENOMSG; - } else if (*len != (size_t)ret) { /* FIXME we should allow receiving less */ - return -EINVAL; + } else if (*len != (size_t)ret) { + return -ECONNRESET; } *len = ret; } + return 0; } @@ -318,7 +318,7 @@ tran_sock_recv_alloc(int sock, struct vfio_user_header *hdr, bool is_reply, return -ENOMSG; } else if (len != (size_t)ret) { free(data); - return -EINVAL; + return -ECONNRESET; } *datap = data; @@ -818,7 +818,7 @@ tran_sock_recv_body(vfu_ctx_t *vfu_ctx, const struct vfio_user_header *hdr, vfu_log(vfu_ctx, LOG_ERR, "msg%#hx: short read: expected=%d, actual=%d", hdr->msg_id, body_size, ret); free(data); - return -EINVAL; + return -ECONNRESET; } *datap = data; |