diff options
| author | Felix Fietkau | 2024-03-29 12:32:35 +0000 |
|---|---|---|
| committer | Felix Fietkau | 2024-03-29 14:09:36 +0000 |
| commit | b6e5548a3ecc562db4c8d5356bdfd9a3fa5e59f8 (patch) | |
| tree | 1703d45e358ddbfd10696bc0526ed2e6412310ea | |
| parent | 488f1d52cfd2fcca8e0f3785311c247d13cb0170 (diff) | |
| download | uclient-b6e5548a3ecc562db4c8d5356bdfd9a3fa5e59f8.tar.gz | |
uclient: defer read notifications to uloop timer
This gets rid of potentially harmful recursion when polling from within the
read callback
Signed-off-by: Felix Fietkau <nbd@nbd.name>
| -rw-r--r-- | uclient-backend.h | 4 | ||||
| -rw-r--r-- | uclient-http.c | 4 | ||||
| -rw-r--r-- | uclient.c | 11 | ||||
| -rw-r--r-- | uclient.h | 1 |
4 files changed, 17 insertions, 3 deletions
diff --git a/uclient-backend.h b/uclient-backend.h index c2b9fd5..b013cde 100644 --- a/uclient-backend.h +++ b/uclient-backend.h @@ -41,5 +41,9 @@ void uclient_backend_set_eof(struct uclient *cl); void uclient_backend_reset_state(struct uclient *cl); struct uclient_url *uclient_get_url(const char *url_str, const char *auth_str); struct uclient_url *uclient_get_url_location(struct uclient_url *url, const char *location); +static inline void uclient_backend_read_notify(struct uclient *cl) +{ + uloop_timeout_set(&cl->read_notify, 1); +} #endif diff --git a/uclient-http.c b/uclient-http.c index 935d50f..83c268f 100644 --- a/uclient-http.c +++ b/uclient-http.c @@ -780,9 +780,7 @@ static void __uclient_notify_read(struct uclient_http *uh) if (uh->state == HTTP_STATE_RECV_DATA) { /* Now it's uclient user turn to read some data */ uloop_timeout_cancel(&uc->connection_timeout); - - if (uc->cb->data_read) - uc->cb->data_read(uc); + uclient_backend_read_notify(uc); } } @@ -239,6 +239,14 @@ static void uclient_connection_timeout(struct uloop_timeout *timeout) uclient_backend_set_error(cl, UCLIENT_ERROR_TIMEDOUT); } +static void __uclient_read_notify(struct uloop_timeout *timeout) +{ + struct uclient *cl = container_of(timeout, struct uclient, read_notify); + + if (cl->cb->data_read) + cl->cb->data_read(cl); +} + struct uclient *uclient_new(const char *url_str, const char *auth_str, const struct uclient_cb *cb) { struct uclient *cl; @@ -257,6 +265,7 @@ struct uclient *uclient_new(const char *url_str, const char *auth_str, const str cl->url = url; cl->timeout_msecs = UCLIENT_DEFAULT_TIMEOUT_MS; cl->connection_timeout.cb = uclient_connection_timeout; + cl->read_notify.cb = __uclient_read_notify; return cl; } @@ -401,6 +410,7 @@ void uclient_disconnect(struct uclient *cl) { uloop_timeout_cancel(&cl->connection_timeout); uloop_timeout_cancel(&cl->timeout); + uloop_timeout_cancel(&cl->read_notify); if (!cl->backend->disconnect) return; @@ -450,6 +460,7 @@ void __hidden uclient_backend_reset_state(struct uclient *cl) cl->eof = false; cl->error_code = 0; uloop_timeout_cancel(&cl->timeout); + uloop_timeout_cancel(&cl->read_notify); } const char * uclient_strerror(unsigned err) @@ -75,6 +75,7 @@ struct uclient { struct blob_attr *meta; struct uloop_timeout connection_timeout; + struct uloop_timeout read_notify; struct uloop_timeout timeout; }; |