author: Alex Rousskov <rousskov@measurement-factory.com>, Christos Tsantilas <chtsanti@users.sourceforge.net>
Coordinator should not send SNMP client FD to strands when broadcasting SNMP
requests. Strands do not need the descriptor and were forgetting to close it,
causing one FD leak on every SNMP query in SMP mode.
Enhance Ipc::TypedMsgHdr to be able to tell whether the message has a FD.
This is a Measurement Factory project
}
}
+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