client: drain text output when exiting
authorJens Axboe <axboe@fb.com>
Wed, 20 Jan 2016 18:22:22 +0000 (11:22 -0700)
committerJens Axboe <axboe@fb.com>
Wed, 20 Jan 2016 18:22:22 +0000 (11:22 -0700)
If we don't, we can lose error messages from the server side. One
example would be for protocol version mismatch - the server will
notify the client, but the client doesn't check for these messages
before exiting.

Signed-off-by: Jens Axboe <axboe@fb.com>
client.c
server.c
server.h

index 6c2a1ef3989e54ad39a41918c870bad301d9bc39..c61301de99dd2bfbcb9c4d35b91108fa0ba276be 100644 (file)
--- a/client.c
+++ b/client.c
@@ -33,6 +33,8 @@ static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd);
 
+static void convert_text(struct fio_net_cmd *cmd);
+
 struct client_ops fio_client_ops = {
        .text           = handle_text,
        .disk_util      = handle_du,
@@ -215,12 +217,33 @@ static int fio_client_dec_jobs_eta(struct client_eta *eta, client_eta_op eta_fn)
        return 1;
 }
 
+static void fio_drain_client_text(struct fio_client *client)
+{
+       do {
+               struct fio_net_cmd *cmd;
+
+               cmd = fio_net_recv_cmd(client->fd, false);
+               if (!cmd)
+                       break;
+
+               if (cmd->opcode != FIO_NET_CMD_TEXT) {
+                       free(cmd);
+                       continue;
+               }
+
+               convert_text(cmd);
+               client->ops->text(client, cmd);
+       } while (1);
+}
+
 static void remove_client(struct fio_client *client)
 {
        assert(client->refs);
 
        dprint(FD_NET, "client: removed <%s>\n", client->hostname);
 
+       fio_drain_client_text(client);
+
        if (!flist_empty(&client->list))
                flist_del_init(&client->list);
 
@@ -1526,7 +1549,7 @@ int fio_handle_client(struct fio_client *client)
 
        dprint(FD_NET, "client: handle %s\n", client->hostname);
 
-       cmd = fio_net_recv_cmd(client->fd);
+       cmd = fio_net_recv_cmd(client->fd, true);
        if (!cmd)
                return 0;
 
index a593a73f436de6a13634238948e6f7e7bfda5f2d..f6f34418e8001a1df4f712d20efb319b41d29eb7 100644 (file)
--- a/server.c
+++ b/server.c
@@ -262,10 +262,17 @@ static int fio_send_data(int sk, const void *p, unsigned int len)
        return fio_sendv_data(sk, &iov, 1);
 }
 
-static int fio_recv_data(int sk, void *p, unsigned int len)
+static int fio_recv_data(int sk, void *p, unsigned int len, bool wait)
 {
+       int flags;
+
+       if (wait)
+               flags = MSG_WAITALL;
+       else
+               flags = MSG_DONTWAIT;
+
        do {
-               int ret = recv(sk, p, len, MSG_WAITALL);
+               int ret = recv(sk, p, len, flags);
 
                if (ret > 0) {
                        len -= ret;
@@ -275,9 +282,11 @@ static int fio_recv_data(int sk, void *p, unsigned int len)
                        continue;
                } else if (!ret)
                        break;
-               else if (errno == EAGAIN || errno == EINTR)
-                       continue;
-               else
+               else if (errno == EAGAIN || errno == EINTR) {
+                       if (wait)
+                               continue;
+                       break;
+               } else
                        break;
        } while (!exit_backend);
 
@@ -326,7 +335,7 @@ static int verify_convert_cmd(struct fio_net_cmd *cmd)
 /*
  * Read (and defragment, if necessary) incoming commands
  */
-struct fio_net_cmd *fio_net_recv_cmd(int sk)
+struct fio_net_cmd *fio_net_recv_cmd(int sk, bool wait)
 {
        struct fio_net_cmd cmd, *tmp, *cmdret = NULL;
        size_t cmd_size = 0, pdu_offset = 0;
@@ -335,7 +344,7 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk)
        void *pdu = NULL;
 
        do {
-               ret = fio_recv_data(sk, &cmd, sizeof(cmd));
+               ret = fio_recv_data(sk, &cmd, sizeof(cmd), wait);
                if (ret)
                        break;
 
@@ -379,7 +388,7 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk)
 
                /* There's payload, get it */
                pdu = (void *) cmdret->payload + pdu_offset;
-               ret = fio_recv_data(sk, pdu, cmd.pdu_len);
+               ret = fio_recv_data(sk, pdu, cmd.pdu_len, wait);
                if (ret)
                        break;
 
@@ -1209,7 +1218,7 @@ static int handle_connection(struct sk_out *sk_out)
                if (ret < 0)
                        break;
 
-               cmd = fio_net_recv_cmd(sk_out->sk);
+               cmd = fio_net_recv_cmd(sk_out->sk, true);
                if (!cmd) {
                        ret = -1;
                        break;
index 12c72759605e7fb0f14602b12bfd3e1230f887ba..05f98e56070c109ae5cd91a6c1dfe7bfb3e5e008 100644 (file)
--- a/server.h
+++ b/server.h
@@ -213,7 +213,7 @@ extern void fio_server_send_du(void);
 extern void fio_server_send_job_options(struct flist_head *, unsigned int);
 extern int fio_server_get_verify_state(const char *, int, void **, int *);
 
-extern struct fio_net_cmd *fio_net_recv_cmd(int sk);
+extern struct fio_net_cmd *fio_net_recv_cmd(int sk, bool wait);
 
 extern int fio_send_iolog(struct thread_data *, struct io_log *, const char *);
 extern void fio_server_send_add_job(struct thread_data *);