* combination with send_one_fd().
*/
- k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
+ k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
if (k < 0)
- return (ssize_t) -errno;
+ return k;
CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET &&
}
}
- if (!found)
+ if (!found) {
cmsg_close_all(&mh);
- /* If didn't receive an FD or any data, return an error. */
- if (k == 0 && !found)
- return -EIO;
+ /* If didn't receive an FD or any data, return an error. */
+ if (k == 0)
+ return -EIO;
+ }
if (found)
*ret_fd = *(int*) CMSG_DATA(found);
return 0;
}
- n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
- if (n < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0; /* Spurious wakeup, try again */
-
- /* If this is any other, real error, then let's stop processing this socket. This of course means we
- * won't take notification messages anymore, but that's still better than busy looping around this:
- * being woken up over and over again but being unable to actually read the message off the socket. */
- return log_error_errno(errno, "Failed to receive notification message: %m");
- }
+ n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
+ if (IN_SET(n, -EAGAIN, -EINTR))
+ return 0; /* Spurious wakeup, try again */
+ if (n < 0)
+ /* If this is any other, real error, then let's stop processing this socket. This of course
+ * means we won't take notification messages anymore, but that's still better than busy
+ * looping around this: being woken up over and over again but being unable to actually read
+ * the message off the socket. */
+ return log_error_errno(n, "Failed to receive notification message: %m");
CMSG_FOREACH(cmsg, &msghdr) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ assert(!fd_array);
fd_array = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ assert(!ucred);
ucred = (struct ucred*) CMSG_DATA(cmsg);
}
}
mh.msg_iov = &iovec;
- n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC);
+ n = recvmsg_safe(fd, &mh, MSG_CMSG_CLOEXEC);
if (n < 0) {
free(iovec.iov_base);
- r = log_error_errno(errno, "Failed to receive datagram: %m");
+ r = log_error_errno(n, "Failed to receive datagram: %m");
goto finish;
}
}
if (!found) {
- log_error("Coredump file descriptor missing.");
- r = -EBADMSG;
+ cmsg_close_all(&mh);
+ r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
+ "Coredump file descriptor missing.");
goto finish;
}
assert(input_fd < 0);
input_fd = *(int*) CMSG_DATA(found);
break;
- }
+ } else
+ cmsg_close_all(&mh);
/* Add trailing NUL byte, in case these are strings */
((char*) iovec.iov_base)[n] = 0;
r = iovw_put(&iovw, iovec.iov_base, iovec.iov_len);
if (r < 0)
goto finish;
-
- cmsg_close_all(&mh);
}
/* Make sure we got all data we really need */
.msg_controllen = sizeof(control),
};
- m = recvmsg(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ m = recvmsg_safe(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (m < 0)
- return -errno;
+ return m;
cmsg_close_all(&mh);
ssize_t n;
int r;
- n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (n < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0;
-
- return -errno;
- }
+ n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (IN_SET(n, -EAGAIN, -EINTR))
+ return 0;
+ if (n < 0)
+ return (int) n;
cmsg_close_all(&msghdr);
iovec = IOVEC_MAKE(s->buffer, s->buffer_size - 1); /* Leave room for trailing NUL we add later */
- n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (n < 0) {
- if (IN_SET(errno, EINTR, EAGAIN))
- return 0;
-
- return log_error_errno(errno, "recvmsg() failed: %m");
+ n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (IN_SET(n, -EINTR, -EAGAIN))
+ return 0;
+ if (n == -EXFULL) {
+ log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
+ return 0;
}
+ if (n < 0)
+ return log_error_errno(n, "recvmsg() failed: %m");
CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ assert(!ucred);
ucred = (struct ucred*) CMSG_DATA(cmsg);
- else if (cmsg->cmsg_level == SOL_SOCKET &&
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_SECURITY) {
+ assert(!label);
label = (char*) CMSG_DATA(cmsg);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
+ assert(!tv);
tv = (struct timeval*) CMSG_DATA(cmsg);
- else if (cmsg->cmsg_level == SOL_SOCKET &&
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
+ assert(!fds);
fds = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
}
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ assert(!ucred);
ucred = (struct ucred *)CMSG_DATA(cmsg);
break;
}
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (k < 0 && errno == ENOTSOCK) {
+ k = recvmsg_safe(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (k == -ENOTSOCK) {
b->prefer_readv = true;
k = readv(b->input_fd, &iov, 1);
+ if (k < 0)
+ k = -errno;
} else
handle_cmsg = true;
}
+ if (k == -EAGAIN)
+ return 0;
if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
- if (k == 0)
+ return (int) k;
+ if (k == 0) {
+ if (handle_cmsg)
+ cmsg_close_all(&mh); /* paranoia, we shouldn't have gotten any fds on EOF */
return -ECONNRESET;
+ }
b->rbuffer_size += k;
mh.msg_control = &control;
mh.msg_controllen = sizeof(control);
- k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (k < 0 && errno == ENOTSOCK) {
+ k = recvmsg_safe(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (k == -ENOTSOCK) {
bus->prefer_readv = true;
k = readv(bus->input_fd, &iov, 1);
+ if (k < 0)
+ k = -errno;
} else
handle_cmsg = true;
}
+ if (k == -EAGAIN)
+ return 0;
if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
- if (k == 0)
+ return (int) k;
+ if (k == 0) {
+ if (handle_cmsg)
+ cmsg_close_all(&mh); /* On EOF we shouldn't have gotten an fd, but let's make sure */
return -ECONNRESET;
+ }
bus->rbuffer_size += k;
return 0;
}
- n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (n < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0;
+ n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (IN_SET(n, -EAGAIN, -EINTR))
+ return 0;
+ if (n < 0)
+ return log_warning_errno(n, "Couldn't read notification socket: %m");
- return log_warning_errno(errno, "Couldn't read notification socket: %m");
- }
cmsg_close_all(&msghdr);
CMSG_FOREACH(cmsg, &msghdr) {
assert(ret_name);
assert(ret_fd);
- n = recvmsg(socket_fd, &mh, MSG_CMSG_CLOEXEC);
+ n = recvmsg_safe(socket_fd, &mh, MSG_CMSG_CLOEXEC);
if (n < 0)
- return -errno;
+ return (int) n;
CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET &&
iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->allocated);
- l = recvmsg(fd, &mh, 0);
- if (l < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0;
-
- return -errno;
- }
+ l = recvmsg_safe(fd, &mh, 0);
+ if (IN_SET(l, -EAGAIN, -EINTR))
+ return 0;
+ if (l < 0)
+ return l;
if (l == 0)
return 0;
- assert(!(mh.msg_flags & MSG_CTRUNC));
assert(!(mh.msg_flags & MSG_TRUNC));
p->size = (size_t) l;
msghdr.msg_control = &control;
msghdr.msg_controllen = sizeof(control);
- n = recvmsg(socket_fd, &msghdr, 0);
+ n = recvmsg_safe(socket_fd, &msghdr, 0);
+ if (IN_SET(n, -EAGAIN, -EINTR))
+ continue;
if (n < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- continue;
-
- r = -errno;
+ r = (int) n;
goto finish;
}
return manager_connect(m);
}
- len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
+ len = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
+ if (len == -EAGAIN)
+ return 0;
if (len < 0) {
- if (errno == EAGAIN)
- return 0;
-
- log_warning("Error receiving message. Disconnecting.");
+ log_warning_errno(len, "Error receiving message, disconnecting: %m");
return manager_connect(m);
}
if (size == 0)
return 0; /* Client disconnects? */
- size = recvmsg(fd, &smsg, 0);
- if (size < 0) {
- if (errno != EINTR)
- return log_error_errno(errno, "Failed to receive ctrl message: %m");
-
+ size = recvmsg_safe(fd, &smsg, 0);
+ if (size == -EINTR)
return 0;
- }
+ if (size < 0)
+ return log_error_errno(size, "Failed to receive ctrl message: %m");
cmsg_close_all(&smsg);
struct ucred *ucred = NULL;
struct worker *worker;
- size = recvmsg(fd, &msghdr, MSG_DONTWAIT);
- if (size < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN)
- /* nothing more to read */
- break;
+ size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
+ if (size == -EINTR)
+ continue;
+ if (size == -EAGAIN)
+ /* nothing more to read */
+ break;
+ if (size < 0)
+ return log_error_errno(size, "Failed to receive message: %m");
+
+ cmsg_close_all(&msghdr);
- return log_error_errno(errno, "Failed to receive message: %m");
- } else if (size != sizeof(struct worker_message)) {
+ if (size != sizeof(struct worker_message)) {
log_warning("Ignoring worker message with invalid size %zi bytes", size);
continue;
}