libubus: do not use uloop_run() inside ubus_complete_request

Avoid unrelated uloop callbacks by using poll() on the ubus fd instead.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
This commit is contained in:
Felix Fietkau 2014-03-18 22:36:36 +01:00
parent 4d7b2ab639
commit 1d5ac421a5
3 changed files with 34 additions and 21 deletions

View file

@ -27,5 +27,7 @@ int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *r
void ubus_process_obj_msg(struct ubus_context*ctx, struct ubus_msghdr *hdr);
void ubus_process_req_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr, int fd);
void ubus_process_pending_msg(struct ubus_context *ctx);
void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout);
#endif

View file

@ -264,6 +264,17 @@ void __hidden ubus_handle_data(struct uloop_fd *u, unsigned int events)
ctx->connection_lost(ctx);
}
void __hidden ubus_poll_data(struct ubus_context *ctx, int timeout)
{
struct pollfd pfd = {
.fd = ctx->sock.fd,
.events = POLLIN | POLLERR,
};
poll(&pfd, 1, timeout);
ubus_handle_data(&ctx->sock, ULOOP_READ);
}
static void
ubus_refresh_state(struct ubus_context *ctx)
{

View file

@ -114,38 +114,32 @@ static void ubus_sync_req_cb(struct ubus_request *req, int ret)
uloop_end();
}
struct ubus_sync_req_cb {
struct uloop_timeout timeout;
struct ubus_request *req;
};
static void ubus_sync_req_timeout_cb(struct uloop_timeout *timeout)
static int64_t get_time_msec(void)
{
struct ubus_sync_req_cb *cb;
struct timespec ts;
int64_t val;
cb = container_of(timeout, struct ubus_sync_req_cb, timeout);
ubus_set_req_status(cb->req, UBUS_STATUS_TIMEOUT);
clock_gettime(CLOCK_MONOTONIC, &ts);
val = (int64_t) ts.tv_sec * 1000LL;
val += ts.tv_nsec / 1000000LL;
return val;
}
int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req,
int timeout)
int req_timeout)
{
struct ubus_sync_req_cb cb;
ubus_complete_handler_t complete_cb = req->complete_cb;
bool registered = ctx->sock.registered;
int status = UBUS_STATUS_NO_DATA;
int64_t timeout = 0, time_end = 0;
if (!registered) {
uloop_init();
ubus_add_uloop(ctx);
}
if (timeout) {
memset(&cb, 0, sizeof(cb));
cb.req = req;
cb.timeout.cb = ubus_sync_req_timeout_cb;
uloop_timeout_set(&cb.timeout, timeout);
}
if (req_timeout)
time_end = get_time_msec() + req_timeout;
ubus_complete_request_async(ctx, req);
req->complete_cb = ubus_sync_req_cb;
@ -153,17 +147,23 @@ 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;
uloop_run();
if (req_timeout) {
timeout = time_end - get_time_msec();
if (timeout <= 0) {
ubus_set_req_status(req, UBUS_STATUS_TIMEOUT);
break;
}
}
ubus_poll_data(ctx, (unsigned int) timeout);
uloop_cancelled = cancelled;
}
ctx->stack_depth--;
if (ctx->stack_depth)
uloop_cancelled = true;
if (timeout)
uloop_timeout_cancel(&cb.timeout);
if (req->status_msg)
status = req->status_code;