<div dir="ltr"><div><div>Quick info follow-up: strace-ing on the PIDs (with high CPU usage) shows a lot of EAGAIN errors from recvfrom() and a lot of recvfrom() + poll() + clock_gettime_monotonic() calls.<br><br></div>Thinking about it, would it make more sense to add a short wait instead [to reduce the throttle] and let it "infinitely" loop ? ["infinitely" loop == loop until it does not error with EAGAIN]<br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 29, 2014 at 4:17 PM, Alexandru Ardelean <span dir="ltr"><<a href="mailto:ardeleanalex@gmail.com" target="_blank">ardeleanalex@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Seems that every once in a while libubus takes up the whole CPU<br>
for certain processes.<br>
<br>
This could be bad code that I keep (re)writing.<br>
<br>
I don't know if it's ok to give up after a certain number of<br>
retries; high CPU usage could indicate I should look deeper<br>
at my logic.<br>
<br>
Which is why I've submitted this patch for review/opinions/comments.<br>
<br>
Can also be reviewed here:<br>
<a href="https://github.com/commodo/ubus/commits/max_retry_mechanism" target="_blank">https://github.com/commodo/ubus/commits/max_retry_mechanism</a><br>
<br>
Thanks<br>
<br>
---<br>
libubus-io.c | 22 ++++++++++++++++------<br>
1 file changed, 16 insertions(+), 6 deletions(-)<br>
<br>
diff --git a/libubus-io.c b/libubus-io.c<br>
index 31dad27..6bc06aa 100644<br>
--- a/libubus-io.c<br>
+++ b/libubus-io.c<br>
@@ -29,6 +29,7 @@<br>
#define STATIC_IOV(_var) { .iov_base = (char *) &(_var), .iov_len = sizeof(_var) }<br>
<br>
#define UBUS_MSGBUF_REDUCTION_INTERVAL 16<br>
+#define UBUS_MAX_RETRIES 256<br>
<br>
static const struct blob_attr_info ubus_policy[UBUS_ATTR_MAX] = {<br>
[UBUS_ATTR_STATUS] = { .type = BLOB_ATTR_INT32 },<br>
@@ -75,6 +76,7 @@ static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)<br>
.msg_controllen = sizeof(fd_buf),<br>
};<br>
int len = 0;<br>
+ int retries = UBUS_MAX_RETRIES;<br>
<br>
do {<br>
int cur_len;<br>
@@ -91,9 +93,9 @@ static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)<br>
switch(errno) {<br>
case EAGAIN:<br>
wait_data(fd, true);<br>
- break;<br>
case EINTR:<br>
- break;<br>
+ if (retries-- > 0)<br>
+ break;<br>
default:<br>
return -1;<br>
}<br>
@@ -115,6 +117,7 @@ static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)<br>
iov->iov_len -= cur_len;<br>
msghdr.msg_iov = iov;<br>
msghdr.msg_iovlen = iov_len;<br>
+ retries = UBUS_MAX_RETRIES;<br>
} while (1);<br>
<br>
/* Should never reach here */<br>
@@ -170,6 +173,7 @@ static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)<br>
.msg_iov = iov,<br>
.msg_iovlen = 1,<br>
};<br>
+ int retries = UBUS_MAX_RETRIES;<br>
<br>
while (iov->iov_len > 0) {<br>
if (wait)<br>
@@ -192,11 +196,16 @@ static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)<br>
bytes = 0;<br>
if (uloop_cancelled)<br>
return 0;<br>
- if (errno == EINTR)<br>
- continue;<br>
-<br>
- if (errno != EAGAIN)<br>
+ switch (errno) {<br>
+ case EINTR:<br>
+ if (retries-- > 0)<br>
+ continue;<br>
+ case EAGAIN:<br>
+ if (retries-- > 0)<br>
+ break;<br>
+ default:<br>
return -1;<br>
+ }<br>
}<br>
if (!wait && !bytes)<br>
return 0;<br>
@@ -210,6 +219,7 @@ static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)<br>
iov->iov_len -= bytes;<br>
iov->iov_base += bytes;<br>
total += bytes;<br>
+ retries = UBUS_MAX_RETRIES;<br>
}<br>
<br>
return total;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.4.5<br>
<br>
</font></span></blockquote></div><br></div>