diff options
author | Felix Fietkau <nbd@nbd.name> | 2017-02-03 18:39:11 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2017-02-03 18:39:15 +0100 |
commit | 91acde66b963e238aba35fb4f2030a147df84cd4 (patch) | |
tree | 6ca0a469c0a0d3d861b9b8ea3c398e929b0f10f6 | |
parent | 763b9b2cf293fb60b5c2ddf34e2500f95200b6b5 (diff) | |
download | ubus-91acde66b963e238aba35fb4f2030a147df84cd4.tar.gz |
libubus: do not modify uloop_cancelled
uloop_cancelled was used for two purposes within ubus_complete_request:
- interrupting recursive requests on SIGINT/SIGTERM
- breaking out of the poll loop in a recursive request that completed
Saving/restorung uloop_cancelled was buggy, leading to SIGTERM not being
processed properly. Simplify the logic by using a separate field for
internal use
Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r-- | libubus-io.c | 12 | ||||
-rw-r--r-- | libubus-req.c | 12 | ||||
-rw-r--r-- | libubus.h | 1 |
3 files changed, 13 insertions, 12 deletions
diff --git a/libubus-io.c b/libubus-io.c index 1075c65..7047ac5 100644 --- a/libubus-io.c +++ b/libubus-io.c @@ -154,9 +154,10 @@ int __hidden ubus_send_msg(struct ubus_context *ctx, uint32_t seq, return ret; } -static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd) +static int recv_retry(struct ubus_context *ctx, struct iovec *iov, bool wait, int *recv_fd) { int bytes, total = 0; + int fd = ctx->sock.fd; static struct { struct cmsghdr h; int fd; @@ -191,7 +192,7 @@ static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd) if (bytes < 0) { bytes = 0; - if (uloop_cancelled) + if (uloop_cancelling() || ctx->cancel_poll) return 0; if (errno == EINTR) continue; @@ -274,7 +275,7 @@ static bool get_next_msg(struct ubus_context *ctx, int *recv_fd) int r; /* receive header + start attribute */ - r = recv_retry(ctx->sock.fd, &iov, false, recv_fd); + r = recv_retry(ctx, &iov, false, recv_fd); if (r <= 0) { if (r < 0) ctx->sock.eof = true; @@ -298,7 +299,7 @@ static bool get_next_msg(struct ubus_context *ctx, int *recv_fd) iov.iov_base = (char *)ctx->msgbuf.data + sizeof(hdrbuf.data); iov.iov_len = blob_len(ctx->msgbuf.data); if (iov.iov_len > 0 && - recv_retry(ctx->sock.fd, &iov, true, NULL) <= 0) + recv_retry(ctx, &iov, true, NULL) <= 0) return false; return true; @@ -311,7 +312,7 @@ void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events) while (get_next_msg(ctx, &recv_fd)) { ubus_process_msg(ctx, &ctx->msgbuf, recv_fd); - if (uloop_cancelled) + if (uloop_cancelling() || ctx->cancel_poll) break; } @@ -326,6 +327,7 @@ void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout) .events = POLLIN | POLLERR, }; + ctx->cancel_poll = false; poll(&pfd, 1, timeout ? timeout : -1); ubus_handle_data(&ctx->sock, ULOOP_READ); } diff --git a/libubus-req.c b/libubus-req.c index db5061c..0c7d589 100644 --- a/libubus-req.c +++ b/libubus-req.c @@ -122,7 +122,7 @@ static void ubus_sync_req_cb(struct ubus_request *req, int ret) { req->status_msg = true; req->status_code = ret; - uloop_end(); + req->ctx->cancel_poll = true; } static int64_t get_time_msec(void) @@ -151,28 +151,26 @@ int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req, ctx->stack_depth++; while (!req->status_msg) { - bool cancelled = uloop_cancelled; - - uloop_cancelled = false; if (req_timeout) { timeout = time_end - get_time_msec(); if (timeout <= 0) { ubus_set_req_status(req, UBUS_STATUS_TIMEOUT); - uloop_cancelled = cancelled; break; } } + ubus_poll_data(ctx, (unsigned int) timeout); - uloop_cancelled = cancelled; if (ctx->sock.eof) { ubus_set_req_status(req, UBUS_STATUS_CONNECTION_FAILED); + ctx->cancel_poll = true; break; } } + ctx->stack_depth--; if (ctx->stack_depth) - uloop_cancelled = true; + ctx->cancel_poll = true; if (req->status_msg) status = req->status_code; @@ -155,6 +155,7 @@ struct ubus_context { uint32_t local_id; uint16_t request_seq; + bool cancel_poll; int stack_depth; void (*connection_lost)(struct ubus_context *ctx); |