diff --git a/cpacfstats/cpacfstats.c b/cpacfstats/cpacfstats.c index 61876f11..98fd22e8 100644 --- a/cpacfstats/cpacfstats.c +++ b/cpacfstats/cpacfstats.c @@ -62,7 +62,7 @@ static int send_query(int s, enum cmd_e cmd, enum ctr_e ctr) m.query.m_ctr = ctr; m.query.m_cmd = cmd; - return send_msg(s, &m); + return send_msg(s, &m, 0); } @@ -71,7 +71,7 @@ static int recv_answer(int s, int *ctr, int *state, uint64_t *value) struct msg m; int rc; - rc = recv_msg(s, &m); + rc = recv_msg(s, &m, 0); if (rc == 0) { if (m.head.m_ver != VERSION) { eprint("Received msg with wrong version %d != %d\n", diff --git a/cpacfstats/cpacfstats.h b/cpacfstats/cpacfstats.h index 77651e4e..a17903aa 100644 --- a/cpacfstats/cpacfstats.h +++ b/cpacfstats/cpacfstats.h @@ -14,7 +14,10 @@ #include "lib/zt_common.h" -#define COPYRIGHT "Copyright IBM Corp. 2015, 2020" +#define COPYRIGHT "Copyright IBM Corp. 2015, 2022" + +#define DEFAULT_SEND_TIMEOUT (2 * 1000) +#define DEFAULT_RECV_TIMEOUT (2 * 1000) int eprint(const char *format, ...); diff --git a/cpacfstats/cpacfstatsd.c b/cpacfstats/cpacfstatsd.c index 99afe388..87c1763d 100644 --- a/cpacfstats/cpacfstatsd.c +++ b/cpacfstats/cpacfstatsd.c @@ -51,7 +51,7 @@ static int recv_query(int s, enum ctr_e *ctr, enum cmd_e *cmd) struct msg m; int rc; - rc = recv_msg(s, &m); + rc = recv_msg(s, &m, DEFAULT_RECV_TIMEOUT); if (rc == 0) { if (m.head.m_ver != VERSION) { eprint("Received msg with wrong version %d != %d\n", @@ -83,7 +83,7 @@ static int send_answer(int s, int ctr, int state, uint64_t value) m.answer.m_state = state; m.answer.m_value = value; - return send_msg(s, &m); + return send_msg(s, &m, DEFAULT_SEND_TIMEOUT); } diff --git a/cpacfstats/stats_sock.c b/cpacfstats/stats_sock.c index 8f81e99a..f3ad5a92 100644 --- a/cpacfstats/stats_sock.c +++ b/cpacfstats/stats_sock.c @@ -3,7 +3,7 @@ * * basic socket and receive/send functions * - * Copyright IBM Corp. 2015, 2017 + * Copyright IBM Corp. 2015, 2022 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -148,7 +148,51 @@ static int __read(int fd, void *buf, int buflen) } -int send_msg(int sfd, struct msg *m) +static int __timedwrite(int fd, const void *buf, int buflen, int timeout) +{ + struct pollfd pfd = { .fd = fd, .events = POLLOUT }; + int i = 0, n; + + while (poll(&pfd, 1, timeout) == 1) { + n = write(fd, buf + i, buflen - i); + if (n < 0) { + if (errno == EINTR) + continue; + else + return n; + } else if (n == 0) { + return i; + } + i += n; + if (buflen == i) + return i; + } + return -1; +} + +static int __timedread(int fd, void *buf, int buflen, int timeout) +{ + struct pollfd pfd = { .fd = fd, .events = POLLIN }; + int i = 0, n; + + while (poll(&pfd, 1, timeout) == 1) { + n = read(fd, buf + i, buflen - i); + if (n < 0) { + if (errno == EINTR) + continue; + else + return n; + } else if (n == 0) { + return i; + } + i += n; + if (buflen == i) + return i; + } + return -1; +} + +int send_msg(int sfd, struct msg *m, int timeout) { int n, len; @@ -166,7 +210,7 @@ int send_msg(int sfd, struct msg *m) return -1; } - n = __write(sfd, m, len); + n = timeout ? __timedwrite(sfd, m, len, timeout) : __write(sfd, m, len); if (n != len) { eprint("Write() error: write()=%d expected %d, errno=%d [%s]\n", n, len, errno, strerror(errno)); @@ -176,12 +220,12 @@ int send_msg(int sfd, struct msg *m) return 0; } -int recv_msg(int sfd, struct msg *m) +int recv_msg(int sfd, struct msg *m, int timeout) { int n, len; len = sizeof(m->head); - n = __read(sfd, m, len); + n = timeout ? __timedread(sfd, m, len, timeout) : __read(sfd, m, len); if (n != len) { eprint("Recv() error: read()=%d expected %d, errno=%d [%s]\n", n, len, errno, strerror(errno)); @@ -200,7 +244,8 @@ int recv_msg(int sfd, struct msg *m) return -1; } - n = __read(sfd, ((char *)m) + sizeof(m->head), len); + n = timeout ? __timedread(sfd, ((char *)m) + sizeof(m->head), len) : + __read(sfd, ((char *)m) + sizeof(m->head), len); if (n != len) { eprint("Recv() error: recv()=%d expected %d, errno=%d [%s]\n", n, len, errno, strerror(errno));