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>
-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)
static struct {
struct cmsghdr h;
int fd;
static struct {
struct cmsghdr h;
int fd;
if (bytes < 0) {
bytes = 0;
if (bytes < 0) {
bytes = 0;
+ if (uloop_cancelling() || ctx->cancel_poll)
return 0;
if (errno == EINTR)
continue;
return 0;
if (errno == EINTR)
continue;
int r;
/* receive header + start attribute */
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;
if (r <= 0) {
if (r < 0)
ctx->sock.eof = true;
iov.iov_base = (char *)ctx->msgbuf.data + sizeof(hdrbuf.data);
iov.iov_len = blob_len(ctx->msgbuf.data);
if (iov.iov_len > 0 &&
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;
return false;
return true;
while (get_next_msg(ctx, &recv_fd)) {
ubus_process_msg(ctx, &ctx->msgbuf, recv_fd);
while (get_next_msg(ctx, &recv_fd)) {
ubus_process_msg(ctx, &ctx->msgbuf, recv_fd);
+ if (uloop_cancelling() || ctx->cancel_poll)
.events = POLLIN | POLLERR,
};
.events = POLLIN | POLLERR,
};
+ ctx->cancel_poll = false;
poll(&pfd, 1, timeout ? timeout : -1);
ubus_handle_data(&ctx->sock, ULOOP_READ);
}
poll(&pfd, 1, timeout ? timeout : -1);
ubus_handle_data(&ctx->sock, ULOOP_READ);
}
{
req->status_msg = true;
req->status_code = ret;
{
req->status_msg = true;
req->status_code = ret;
+ req->ctx->cancel_poll = true;
}
static int64_t get_time_msec(void)
}
static int64_t get_time_msec(void)
ctx->stack_depth++;
while (!req->status_msg) {
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);
if (req_timeout) {
timeout = time_end - get_time_msec();
if (timeout <= 0) {
ubus_set_req_status(req, UBUS_STATUS_TIMEOUT);
- uloop_cancelled = cancelled;
ubus_poll_data(ctx, (unsigned int) timeout);
ubus_poll_data(ctx, (unsigned int) timeout);
- uloop_cancelled = cancelled;
if (ctx->sock.eof) {
ubus_set_req_status(req, UBUS_STATUS_CONNECTION_FAILED);
if (ctx->sock.eof) {
ubus_set_req_status(req, UBUS_STATUS_CONNECTION_FAILED);
+ ctx->cancel_poll = true;
ctx->stack_depth--;
if (ctx->stack_depth)
ctx->stack_depth--;
if (ctx->stack_depth)
- uloop_cancelled = true;
+ ctx->cancel_poll = true;
if (req->status_msg)
status = req->status_code;
if (req->status_msg)
status = req->status_code;
uint32_t local_id;
uint16_t request_seq;
uint32_t local_id;
uint16_t request_seq;
int stack_depth;
void (*connection_lost)(struct ubus_context *ctx);
int stack_depth;
void (*connection_lost)(struct ubus_context *ctx);