make the socket non-blocking, explicitly wait for data using poll()

This commit is contained in:
Felix Fietkau 2011-09-09 17:53:22 +02:00
parent d9211374c5
commit 7c59d4069c

View file

@ -16,6 +16,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <poll.h>
#include <libubox/blob.h> #include <libubox/blob.h>
#include <libubox/blobmsg.h> #include <libubox/blobmsg.h>
@ -88,6 +89,14 @@ out:
return err; return err;
} }
static void wait_data(int fd, bool write)
{
struct pollfd pfd = { .fd = fd };
pfd.events = write ? POLLOUT : POLLIN;
poll(&pfd, 1, 0);
}
static int writev_retry(int fd, struct iovec *iov, int iov_len) static int writev_retry(int fd, struct iovec *iov, int iov_len)
{ {
int len = 0; int len = 0;
@ -97,9 +106,7 @@ static int writev_retry(int fd, struct iovec *iov, int iov_len)
if (cur_len < 0) { if (cur_len < 0) {
switch(errno) { switch(errno) {
case EAGAIN: case EAGAIN:
/* turn off non-blocking mode */ wait_data(fd, true);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) &
~O_NONBLOCK);
break; break;
case EINTR: case EINTR:
break; break;
@ -165,6 +172,9 @@ static bool recv_retry(int fd, struct iovec *iov, bool wait)
int bytes; int bytes;
while (iov->iov_len > 0) { while (iov->iov_len > 0) {
if (wait)
wait_data(fd, false);
bytes = read(fd, iov->iov_base, iov->iov_len); bytes = read(fd, iov->iov_base, iov->iov_len);
if (bytes < 0) { if (bytes < 0) {
bytes = 0; bytes = 0;
@ -860,6 +870,8 @@ struct ubus_context *ubus_connect(const char *path)
if (!ctx->local_id) if (!ctx->local_id)
goto error_close; goto error_close;
fcntl(ctx->sock.fd, F_SETFL, fcntl(ctx->sock.fd, F_GETFL) | O_NONBLOCK);
return ctx; return ctx;
error_free_buf: error_free_buf: