diff options
author | Trumeet <yuuta@yuuta.moe> | 2022-08-09 17:15:45 -0700 |
---|---|---|
committer | Trumeet <yuuta@yuuta.moe> | 2022-08-09 17:15:45 -0700 |
commit | 7edaa14c2c822e5b776edaa6534753b258d29488 (patch) | |
tree | 7c6dba03c89d3d9745a40d03e5b45c1f9cdf3938 /client/acronc/handler_socket.c | |
parent | 1d42944d172cbc725cd025aea1c364c3f13a38e5 (diff) | |
download | acron-7edaa14c2c822e5b776edaa6534753b258d29488.tar acron-7edaa14c2c822e5b776edaa6534753b258d29488.tar.gz acron-7edaa14c2c822e5b776edaa6534753b258d29488.tar.bz2 acron-7edaa14c2c822e5b776edaa6534753b258d29488.zip |
fix(libacron): infinite loop when wic_parse returns 0
This is a rather complicated way to fix backlogging issues. It asks the client to pass partial buffer, and the client also must retry with NULL buffer if ac_receive returns AC_E_AGAIN.
Diffstat (limited to 'client/acronc/handler_socket.c')
-rw-r--r-- | client/acronc/handler_socket.c | 66 |
1 files changed, 33 insertions, 33 deletions
diff --git a/client/acronc/handler_socket.c b/client/acronc/handler_socket.c index 2dfda5e..c0a9923 100644 --- a/client/acronc/handler_socket.c +++ b/client/acronc/handler_socket.c @@ -125,50 +125,50 @@ static void on_read(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { } int r; ac_obj_t *obj = NULL; - if ((r = ac_receive(ac_conn, buf->base, nread, &obj))) { - LOGEV("Cannot parse the response (%d).", r); - /* libac error. Socket is working. */ - ex(false); - return; - } - - if (!ready) { - enum ac_connection_state state; - if ((r = ac_get_state(ac_conn, &state))) { - LOGEV("Cannot get state (%d).", r); + size_t pos = 0; + size_t read = 0; + bool again = false; + while (read < nread || again) { + if (again) { + LOGD("Clearing backlog."); + r = ac_receive(ac_conn, NULL, 0, 0, &obj, NULL); + again = false; + } else { + r = ac_receive(ac_conn, buf->base, pos, nread, &obj, &read); + pos += read; + } + if (r == AC_E_AGAIN) { + again = true; + } else if (r) { + LOGEV("Cannot parse the response (%d).", r); /* libac error. Socket is working. */ ex(false); + free(buf->base); return; } - if (state == AC_STATE_READY) { - ready = true; - if ((cb_ready())) { - /* acronc error. Socket is working. */ - ex(false); - return; - } - } - } - if (obj) { - LOGDV("Got object: %p", obj); - /* uv_async_send is unreliable, and missed messages will cause memory leak. */ - if (cb_recv(obj)) { - /* acronc error. Socket is working. */ - ex(false); - } - LOGD("Clearing backlog."); - while (true) { - if ((r = ac_receive(ac_conn, NULL, 0, &obj))) { - LOGEV("Cannot clear backlog (%d).", r); + if (!ready) { + enum ac_connection_state state; + if ((r = ac_get_state(ac_conn, &state))) { + LOGEV("Cannot get state (%d).", r); /* libac error. Socket is working. */ free(buf->base); ex(false); return; } - if (!obj) { - break; + if (state == AC_STATE_READY) { + ready = true; + if ((cb_ready())) { + /* acronc error. Socket is working. */ + free(buf->base); + ex(false); + return; + } } + } + if (obj) { + LOGDV("Got object: %p", obj); + /* uv_async_send is unreliable, and missed messages will cause memory leak. */ if (cb_recv(obj)) { /* acronc error. Socket is working. */ ex(false); |