libubus: detect read/write errors and set the eof flag, even if uloop is not used as main event loop

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
This commit is contained in:
Felix Fietkau 2013-08-08 22:42:50 +02:00
parent 62bfc16a09
commit b20a8a01c7

View file

@ -94,6 +94,7 @@ int __hidden ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
struct iovec iov[2] = { struct iovec iov[2] = {
STATIC_IOV(hdr) STATIC_IOV(hdr)
}; };
int ret;
hdr.version = 0; hdr.version = 0;
hdr.type = cmd; hdr.type = cmd;
@ -108,37 +109,45 @@ int __hidden ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
iov[1].iov_base = (char *) msg; iov[1].iov_base = (char *) msg;
iov[1].iov_len = blob_raw_len(msg); iov[1].iov_len = blob_raw_len(msg);
return writev_retry(ctx->sock.fd, iov, ARRAY_SIZE(iov)); ret = writev_retry(ctx->sock.fd, iov, ARRAY_SIZE(iov));
if (ret < 0)
ctx->sock.eof = true;
return ret;
} }
static bool recv_retry(int fd, struct iovec *iov, bool wait) static int recv_retry(int fd, struct iovec *iov, bool wait)
{ {
int bytes; int bytes, total = 0;
while (iov->iov_len > 0) { while (iov->iov_len > 0) {
if (wait) if (wait)
wait_data(fd, false); wait_data(fd, false);
bytes = read(fd, iov->iov_base, iov->iov_len); bytes = read(fd, iov->iov_base, iov->iov_len);
if (!bytes)
return -1;
if (bytes < 0) { if (bytes < 0) {
bytes = 0; bytes = 0;
if (uloop_cancelled) if (uloop_cancelled)
return false; return 0;
if (errno == EINTR) if (errno == EINTR)
continue; continue;
if (errno != EAGAIN) if (errno != EAGAIN)
return false; return -1;
} }
if (!wait && !bytes) if (!wait && !bytes)
return false; return 0;
wait = true; wait = true;
iov->iov_len -= bytes; iov->iov_len -= bytes;
iov->iov_base += bytes; iov->iov_base += bytes;
total += bytes;
} }
return true; return total;
} }
static bool ubus_validate_hdr(struct ubus_msghdr *hdr) static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
@ -158,11 +167,17 @@ static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
static bool get_next_msg(struct ubus_context *ctx) static bool get_next_msg(struct ubus_context *ctx)
{ {
struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr); struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr);
int r;
/* receive header + start attribute */ /* receive header + start attribute */
iov.iov_len += sizeof(struct blob_attr); iov.iov_len += sizeof(struct blob_attr);
if (!recv_retry(ctx->sock.fd, &iov, false)) r = recv_retry(ctx->sock.fd, &iov, false);
if (r <= 0) {
if (r < 0)
ctx->sock.eof = true;
return false; return false;
}
iov.iov_len = blob_len(ctx->msgbuf.hdr.data); iov.iov_len = blob_len(ctx->msgbuf.hdr.data);
if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true)) if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true))