ustream: prevent recursive calls to the read callback master
authorFelix Fietkau <nbd@nbd.name>
Fri, 29 Mar 2024 09:23:28 +0000 (10:23 +0100)
committerFelix Fietkau <nbd@nbd.name>
Fri, 29 Mar 2024 12:59:21 +0000 (13:59 +0100)
Simplifies stacked ustreams and calling poll from the read function.
Reuse an unused leftover struct member in order to not break ABI.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
ustream.c
ustream.h

index d36ce080ec10067cd8f25d52d0da72285e1048eb..d200dbab0315b0612b5741b5b53bdc7688887e9a 100644 (file)
--- a/ustream.c
+++ b/ustream.c
@@ -24,6 +24,8 @@
 
 #include "ustream.h"
 
+#define CB_PENDING_READ        (1 << 0)
+
 static void ustream_init_buf(struct ustream_buf *buf, int len)
 {
        if (!len)
@@ -133,7 +135,6 @@ void ustream_init_defaults(struct ustream *s)
        s->state_change.cb = ustream_state_change_cb;
        s->write_error = false;
        s->eof = false;
-       s->eof_write_done = false;
        s->read_blocked = 0;
 
        s->r.buffers = 0;
@@ -301,7 +302,6 @@ char *ustream_reserve(struct ustream *s, int len, int *maxlen)
 void ustream_fill_read(struct ustream *s, int len)
 {
        struct ustream_buf *buf = s->r.data_tail;
-       int n = len;
        int maxlen;
 
        s->r.data_bytes += len;
@@ -321,8 +321,14 @@ void ustream_fill_read(struct ustream *s, int len)
                buf = buf->next;
        } while (len);
 
-       if (s->notify_read)
-               s->notify_read(s, n);
+       if (s->notify_read) {
+               if (s->pending_cb & CB_PENDING_READ)
+                       return;
+
+               s->pending_cb |= CB_PENDING_READ;
+               s->notify_read(s, s->r.data_bytes);
+               s->pending_cb &= ~CB_PENDING_READ;
+       }
 }
 
 char *ustream_get_read_buf(struct ustream *s, int *buflen)
index 9a306180bc20f7ac87ee95b426fddbbba7f05055..b8443e5177eeed7b29f41a67c921fdf1b2e47626 100644 (file)
--- a/ustream.h
+++ b/ustream.h
@@ -114,7 +114,8 @@ struct ustream {
         */
        bool string_data;
        bool write_error;
-       bool eof, eof_write_done;
+       bool eof;
+       uint8_t pending_cb;
 
        enum read_blocked_reason read_blocked;
 };