From 63c53e21fed731bdc98846ba20227a39203c72dc Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Mon, 26 Jul 2021 18:57:17 +0800 Subject: [PATCH] base: Add SOCK_CLOEXEC when creating/accepting sockets Prevents any forked process (e.g. diod) from holding on the sockets if gem5 crashes. This flag is only supported on Linux, so we stub it out on other platforms. Test: ls -l /proc/$DIOD_PID/fd shows a lot less fds. Change-Id: I6bc195ed3bd638ab28ff7690f43afce030fa28c7 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48623 Reviewed-by: Gabe Black Maintainer: Gabe Black Tested-by: kokoro --- src/base/socket.cc | 26 ++++++++++++++++++++++++-- src/base/socket.hh | 10 ++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/base/socket.cc b/src/base/socket.cc index fa61ea4cfc..f0aeb01992 100644 --- a/src/base/socket.cc +++ b/src/base/socket.cc @@ -81,6 +81,28 @@ ListenSocket::loopbackOnly() bindToLoopback = true; } +// Wrappers to stub out SOCK_CLOEXEC/accept4 availability + +int +ListenSocket::socketCloexec(int domain, int type, int protocol) +{ +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif + return ::socket(domain, type, protocol); +} + +int +ListenSocket::acceptCloexec(int sockfd, struct sockaddr *addr, + socklen_t *addrlen) +{ +#if defined(_GNU_SOURCE) && defined(SOCK_CLOEXEC) + return ::accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); +#else + return ::accept(sockfd, addr, addrlen); +#endif +} + //////////////////////////////////////////////////////////////////////// // // @@ -104,7 +126,7 @@ ListenSocket::listen(int port, bool reuse) // only create socket if not already created by a previous call if (fd == -1) { - fd = ::socket(PF_INET, SOCK_STREAM, 0); + fd = socketCloexec(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (fd < 0) panic("Can't create socket:%s !", strerror(errno)); } @@ -150,7 +172,7 @@ ListenSocket::accept(bool nodelay) { struct sockaddr_in sockaddr; socklen_t slen = sizeof (sockaddr); - int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); + int sfd = acceptCloexec(fd, (struct sockaddr *)&sockaddr, &slen); if (sfd != -1 && nodelay) { int i = 1; if (::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, diff --git a/src/base/socket.hh b/src/base/socket.hh index b9b257c10b..4ed6185152 100644 --- a/src/base/socket.hh +++ b/src/base/socket.hh @@ -29,6 +29,9 @@ #ifndef __SOCKET_HH__ #define __SOCKET_HH__ +#include +#include + namespace gem5 { @@ -59,6 +62,13 @@ class ListenSocket */ static void cleanup(); + private: + /* Create a socket, adding SOCK_CLOEXEC if available. */ + static int socketCloexec(int domain, int type, int protocol); + /* Accept a connection, adding SOCK_CLOEXEC if available. */ + static int acceptCloexec(int sockfd, struct sockaddr *addr, + socklen_t *addrlen); + public: /**