1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-04 21:47:31 +03:00

bus: fall back to readv/writev if recvmsg/sendmsg don't work

This commit is contained in:
Lennart Poettering 2013-03-31 20:19:18 +02:00
parent e82c950997
commit 15d5af8145
3 changed files with 136 additions and 91 deletions

View File

@ -83,6 +83,8 @@ struct sd_bus {
bool ucred_valid:1;
bool is_server:1;
bool anonymous_auth:1;
bool prefer_readv:1;
bool prefer_writev:1;
void *rbuffer;
size_t rbuffer_size;

View File

@ -75,7 +75,6 @@ bool bus_socket_auth_needs_write(sd_bus *b) {
}
static int bus_socket_write_auth(sd_bus *b) {
struct msghdr mh;
ssize_t k;
assert(b);
@ -84,16 +83,26 @@ static int bus_socket_write_auth(sd_bus *b) {
if (!bus_socket_auth_needs_write(b))
return 0;
if (b->prefer_writev)
k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
else {
struct msghdr mh;
zero(mh);
mh.msg_iov = b->auth_iovec + b->auth_index;
mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
if (k < 0 && errno == ENOTSOCK) {
b->prefer_writev = true;
k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
}
}
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
return 1;
}
@ -431,6 +440,7 @@ static int bus_socket_read_auth(sd_bus *b) {
CMSG_SPACE(NAME_MAX)]; /*selinux label */
} control;
struct cmsghdr *cmsg;
bool handle_cmsg = false;
assert(b);
assert(b->state == BUS_AUTHENTICATING);
@ -457,6 +467,9 @@ static int bus_socket_read_auth(sd_bus *b) {
iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
iov.iov_len = n - b->rbuffer_size;
if (b->prefer_readv)
k = readv(b->input_fd, &iov, 1);
else {
zero(mh);
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
@ -464,6 +477,12 @@ static int bus_socket_read_auth(sd_bus *b) {
mh.msg_controllen = sizeof(control);
k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
b->prefer_readv = true;
k = readv(b->input_fd, &iov, 1);
} else
handle_cmsg = true;
}
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
if (k == 0)
@ -471,6 +490,7 @@ static int bus_socket_read_auth(sd_bus *b) {
b->rbuffer_size += k;
if (handle_cmsg) {
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
@ -499,6 +519,7 @@ static int bus_socket_read_auth(sd_bus *b) {
b->label[l] = 0;
}
}
}
r = bus_socket_auth_verify(b);
if (r != 0)
@ -687,7 +708,6 @@ int bus_socket_take_fd(sd_bus *b) {
}
int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
struct msghdr mh;
struct iovec *iov;
ssize_t k;
size_t n;
@ -700,6 +720,18 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
if (*idx >= m->size)
return 0;
n = m->n_iovec * sizeof(struct iovec);
iov = alloca(n);
memcpy(iov, m->iovec, n);
j = 0;
iovec_advance(iov, &j, *idx);
if (bus->prefer_writev)
k = writev(bus->output_fd, iov, m->n_iovec);
else {
struct msghdr mh;
zero(mh);
if (m->n_fds > 0) {
@ -713,17 +745,16 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
}
n = m->n_iovec * sizeof(struct iovec);
iov = alloca(n);
memcpy(iov, m->iovec, n);
j = 0;
iovec_advance(iov, &j, *idx);
mh.msg_iov = iov;
mh.msg_iovlen = m->n_iovec;
k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
if (k < 0 && errno == ENOTSOCK) {
bus->prefer_writev = true;
k = writev(bus->output_fd, iov, m->n_iovec);
}
}
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
@ -835,6 +866,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
CMSG_SPACE(NAME_MAX)]; /*selinux label */
} control;
struct cmsghdr *cmsg;
bool handle_cmsg;
assert(bus);
assert(m);
@ -857,6 +889,9 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
iov.iov_len = need - bus->rbuffer_size;
if (bus->prefer_readv)
k = readv(bus->input_fd, &iov, 1);
else {
zero(mh);
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
@ -864,6 +899,12 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
mh.msg_controllen = sizeof(control);
k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
if (k < 0 && errno == ENOTSOCK) {
bus->prefer_readv = true;
k = readv(bus->input_fd, &iov, 1);
} else
handle_cmsg = true;
}
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
if (k == 0)
@ -871,6 +912,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
bus->rbuffer_size += k;
if (handle_cmsg) {
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
@ -912,6 +954,7 @@ int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
bus->label[l] = 0;
}
}
}
r = bus_socket_read_message_need(bus, &need);
if (r < 0)

View File

@ -57,7 +57,7 @@ int sd_bus_open_user(sd_bus **ret);
int sd_bus_new(sd_bus **ret);
int sd_bus_set_address(sd_bus *bus, const char *address);
int sd_bus_set_fd(sd_bus *bus, int fd);
int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd);
int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]);
int sd_bus_set_bus_client(sd_bus *bus, int b);
int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id);