When a tracee fails to receive a message we sent it, drain that message from the socket buffer
Resolves #2628
diff --git a/src/AutoRemoteSyscalls.cc b/src/AutoRemoteSyscalls.cc
index 07e7649..3fd3658 100644
--- a/src/AutoRemoteSyscalls.cc
+++ b/src/AutoRemoteSyscalls.cc
@@ -433,15 +433,14 @@
remote.task()->write_bytes_helper(remote_buf.get().cast<char>(),
sizeof(msg), &msg, &ok);
-
if (!ok) {
return -ESRCH;
}
int ret = 0;
- if (!has_socketcall_syscall(Arch::arch())) {
- ret = remote.syscall(Arch::recvmsg, child_sock, msg.remote_msg(), 0);
- } else {
+ if (has_socketcall_syscall(Arch::arch())) {
ret = remote.syscall(Arch::socketcall, SYS_RECVMSG, msg.remote_sc_args());
+ } else {
+ ret = remote.syscall(Arch::recvmsg, child_sock, msg.remote_msg(), 0);
}
if (ret < 0) {
return ret;
@@ -457,7 +456,7 @@
fd_message<NativeArch> msg;
struct msghdr *msgp = (struct msghdr*)&msg.msg;
if (0 > recvmsg(sock, msgp, MSG_CMSG_CLOEXEC)) {
- FATAL() << "Failed to receive fd";
+ return -1;
}
struct cmsghdr* cmsg = CMSG_FIRSTHDR(msgp);
@@ -493,6 +492,7 @@
ASSERT(t, child_syscall_result > 0) << "Failed to sendmsg() in tracee; err="
<< errno_name(-child_syscall_result);
int our_fd = recvmsg_socket(task()->session().tracee_socket_fd());
+ ASSERT(t, our_fd >= 0) << "Failed to receive fd";
return ScopedFd(our_fd);
}
@@ -511,7 +511,13 @@
long child_syscall_result =
child_recvmsg<Arch>(*this, task()->session().tracee_fd_number());
if (child_syscall_result == -ESRCH) {
- return ScopedFd();
+ /* The child did not receive the message. Read it out of the socket
+ buffer so it doesn't get read by another child later! */
+ int fd = recvmsg_socket(task()->session().tracee_socket_receiver_fd());
+ if (fd >= 0) {
+ close(fd);
+ }
+ return -ESRCH;
}
ASSERT(t, child_syscall_result >= 0) << "Failed to recvmsg() in tracee; err="
<< errno_name(-child_syscall_result);