}
}
+bool
+Ipc::TypedMsgHdr::hasFd() const
+{
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
+ return cmsg &&
+ cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS;
+}
+
void
Ipc::TypedMsgHdr::putFd(int fd)
{
Must(fd >= 0);
+ Must(!hasFd());
allocControl();
const int fdCount = 1;
int *fdStore = reinterpret_cast<int*>(CMSG_DATA(cmsg));
memcpy(fdStore, &fd, fdCount * sizeof(int));
msg_controllen = cmsg->cmsg_len;
+
+ Must(hasFd());
}
int
Ipc::TypedMsgHdr::getFd() const
{
Must(msg_control && msg_controllen);
+ Must(hasFd());
struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
Must(cmsg->cmsg_level == SOL_SOCKET);
/* access to a "file" descriptor that can be passed between processes */
void putFd(int aFd); ///< stores descriptor
- int getFd() const; ///< returns descriptor
+ int getFd() const; ///< returns stored descriptor
+ bool hasFd() const; ///< whether the message has a descriptor stored
/* raw, type-independent access for I/O */
void prepForReading(); ///< reset and provide all buffers
closer = asyncCall(49, 5, "Snmp::Inquirer::noteCommClosed",
CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
comm_add_close_handler(conn->fd, closer);
+
+ // forget client FD to avoid sending it to strands that may forget to close
+ if (Request *snmpRequest = dynamic_cast<Request*>(request.getRaw()))
+ snmpRequest->fd = -1;
}
/// closes our copy of the client connection socket
session.unpack(msg);
msg.getPod(address);
- fd = msg.getFd();
+ // Requests from strands have FDs. Requests from Coordinator do not.
+ fd = msg.hasFd() ? msg.getFd() : -1;
}
void
session.pack(msg);
msg.putPod(address);
- msg.putFd(fd);
+ // Requests sent to Coordinator have FDs. Requests sent to strands do not.
+ if (fd >= 0)
+ msg.putFd(fd);
}
Ipc::Request::Pointer