diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2020-10-03 21:30:57 +0200 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2020-10-03 21:30:57 +0200 |
commit | 08b2de406a45f98cc2b46a35719f4c9d1a87c1b5 (patch) | |
tree | 0c8b8cdfd2fbdab0cb630574e7572319e14a7c90 | |
parent | d096bb626f8dd78b6ba1ac9c2d19e567cb88827e (diff) |
ssh/tomsg_clientlib: Fix stuck-data bug in tomsg_next_event
The issue was that I have too many buffering layers. The bug occurred
when the sshnc layer had received some amount of data, some of which
(but not all of which) was passed on to tomsg_clientlib via
sshnc_maybe_recv in receive_more_data. If the data that _was_ passed on
did not constitute a full event, tomsg_clientlib did not ask for more
data from the sshnc layer; it would only get received the next time
there was actual data on the _socket_, at which point poll(2) would
ensure the whole chain gets looped through another time.
-rw-r--r-- | ssh/tomsg_clientlib.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/ssh/tomsg_clientlib.c b/ssh/tomsg_clientlib.c index df22a1e..260b785 100644 --- a/ssh/tomsg_clientlib.c +++ b/ssh/tomsg_clientlib.c @@ -938,12 +938,18 @@ enum tomsg_retval tomsg_next_event(struct tomsg_client *client, struct tomsg_eve enum tomsg_retval ret = find_handle_next_line(client, eventp); if (ret != TOMSG_ERR_AGAIN) return ret; - // Otherwise, try to receive more data. - ret = receive_more_data(client); - if (ret != TOMSG_OK) return ret; - - // And then handle any line that might be completed at this point. - return find_handle_next_line(client, eventp); + // Otherwise, try to receive more data until either there is no more data + // anymore, or we have a complete event. + while (true) { + ret = receive_more_data(client); + if (ret != TOMSG_OK) return ret; + + // Handle any line that might be completed at this point. If that + // produces an event or an error, return it; otherwise loop and receive + // more data. + ret = find_handle_next_line(client, eventp); + if (ret != TOMSG_ERR_AGAIN) return ret; + } } #define SEND_FMT0(client, tag, fmt) do { \ |