Index: include/lldb/Host/Socket.h =================================================================== --- include/lldb/Host/Socket.h +++ include/lldb/Host/Socket.h @@ -56,16 +56,16 @@ // Initialize a Tcp Socket object in listening mode. listen and accept are implemented // separately because the caller may wish to manipulate or query the socket after it is // initialized, but before entering a blocking accept. - static Error TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate* predicate); - static Error TcpConnect(llvm::StringRef host_and_port, Socket *&socket); - static Error UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket); - static Error UnixDomainConnect(llvm::StringRef host_and_port, Socket *&socket); - static Error UnixDomainAccept(llvm::StringRef host_and_port, Socket *&socket); + static Error TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate* predicate); + static Error TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); + static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); // Blocks on a listening socket until a connection is received. This method assumes that // |this->m_socket| is a listening socket, created via either TcpListen() or via the native // constructor that takes a NativeSocket, which itself was created via a call to |listen()| - Error BlockingAccept(llvm::StringRef host_and_port, Socket *&socket); + Error BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); Index: include/lldb/Host/posix/ConnectionFileDescriptorPosix.h =================================================================== --- include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -34,7 +34,7 @@ class ConnectionFileDescriptor : public Connection { public: - ConnectionFileDescriptor(); + ConnectionFileDescriptor(bool child_processes_inherit = false); ConnectionFileDescriptor(int fd, bool owns_fd); @@ -67,6 +67,9 @@ uint16_t GetListeningPort(uint32_t timeout_sec); + bool GetChildProcessesInherit() const; + void SetChildProcessesInherit(bool child_processes_inherit); + protected: void OpenCommandPipe(); @@ -94,6 +97,7 @@ std::atomic m_shutting_down; // This marks that we are shutting down so if we get woken up from // BytesAvailable to disconnect, we won't try to read again. bool m_waiting_for_accept; + bool m_child_processes_inherit; private: DISALLOW_COPY_AND_ASSIGN(ConnectionFileDescriptor); Index: source/Host/common/Socket.cpp =================================================================== --- source/Host/common/Socket.cpp +++ source/Host/common/Socket.cpp @@ -55,6 +55,33 @@ #endif #endif // #ifdef __ANDROID__ +namespace { + +NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit) +{ + auto socketType = type; +#ifdef SOCK_CLOEXEC + if (!child_processes_inherit) { + socketType |= SOCK_CLOEXEC; + } +#endif + return ::socket (domain, socketType, protocol); +} + +NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit) +{ +#ifdef SOCK_CLOEXEC + int flags = 0; + if (!child_processes_inherit) { + flags |= SOCK_CLOEXEC; + } + return ::accept4 (sockfd, addr, addrlen, flags); +#else + return ::accept (sockfd, addr, addrlen); +#endif +} +} + Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close) : IOObject(eFDTypeSocket, should_close) , m_protocol(protocol) @@ -68,7 +95,7 @@ Close(); } -Error Socket::TcpConnect(llvm::StringRef host_and_port, Socket *&socket) +Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { // Store the result in a unique_ptr in case we error out, the memory will get correctly freed. std::unique_ptr final_socket; @@ -86,7 +113,7 @@ return error; // Create the socket - sock = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit); if (sock == kInvalidSocketValue) { // TODO: On Windows, use WSAGetLastError(). @@ -140,7 +167,7 @@ return error; } -Error Socket::TcpListen(llvm::StringRef host_and_port, Socket *&socket, Predicate* predicate) +Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate* predicate) { std::unique_ptr listen_socket; NativeSocket listen_sock = kInvalidSocketValue; @@ -149,7 +176,7 @@ const sa_family_t family = AF_INET; const int socktype = SOCK_STREAM; const int protocol = IPPROTO_TCP; - listen_sock = ::socket (family, socktype, protocol); + listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit); if (listen_sock == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -211,7 +238,7 @@ return error; } -Error Socket::BlockingAccept(llvm::StringRef host_and_port, Socket *&socket) +Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { Error error; std::string host_str; @@ -250,7 +277,10 @@ #endif socklen_t accept_addr_len = sizeof accept_addr; - int sock = ::accept (this->GetNativeSocket(), (struct sockaddr *)&accept_addr, &accept_addr_len); + int sock = Accept (this->GetNativeSocket(), + (struct sockaddr *)&accept_addr, + &accept_addr_len, + child_processes_inherit); if (sock == kInvalidSocketValue) { @@ -295,7 +325,7 @@ } -Error Socket::UdpConnect(llvm::StringRef host_and_port, Socket *&send_socket, Socket *&recv_socket) +Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) { std::unique_ptr final_send_socket; std::unique_ptr final_recv_socket; @@ -315,7 +345,7 @@ // Setup the receiving end of the UDP connection on this localhost // on port zero. After we bind to port zero we can read the port. - final_recv_fd = ::socket (AF_INET, SOCK_DGRAM, 0); + final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit); if (final_recv_fd == kInvalidSocketValue) { // Socket creation failed... @@ -366,9 +396,10 @@ service_info_ptr != NULL; service_info_ptr = service_info_ptr->ai_next) { - final_send_fd = ::socket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol); + final_send_fd = ::CreateSocket (service_info_ptr->ai_family, + service_info_ptr->ai_socktype, + service_info_ptr->ai_protocol, + child_processes_inherit); if (final_send_fd != kInvalidSocketValue) { @@ -395,7 +426,7 @@ return error; } -Error Socket::UnixDomainConnect(llvm::StringRef name, Socket *&socket) +Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; #ifndef LLDB_DISABLE_POSIX @@ -403,7 +434,7 @@ // Open the socket that was passed in as an option struct sockaddr_un saddr_un; - int fd = ::socket (AF_UNIX, SOCK_STREAM, 0); + int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); if (fd == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -432,7 +463,7 @@ return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, Socket *&socket) +Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; #ifndef LLDB_DISABLE_POSIX @@ -442,7 +473,7 @@ NativeSocket listen_fd = kInvalidSocketValue; NativeSocket socket_fd = kInvalidSocketValue; - listen_fd = ::socket (AF_UNIX, SOCK_STREAM, 0); + listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); if (listen_fd == kInvalidSocketValue) { error.SetErrorToErrno(); @@ -464,7 +495,7 @@ { if (::listen (listen_fd, 5) == 0) { - socket_fd = ::accept (listen_fd, NULL, 0); + socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit); if (socket_fd > 0) { final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true)); Index: source/Host/posix/ConnectionFileDescriptorPosix.cpp =================================================================== --- source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -49,12 +49,13 @@ using namespace lldb; using namespace lldb_private; -ConnectionFileDescriptor::ConnectionFileDescriptor() +ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) : Connection() , m_pipe() , m_mutex(Mutex::eMutexTypeRecursive) , m_shutting_down(false) , m_waiting_for_accept(false) + , m_child_processes_inherit(child_processes_inherit) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); if (log) @@ -67,6 +68,7 @@ , m_mutex(Mutex::eMutexTypeRecursive) , m_shutting_down(false) , m_waiting_for_accept(false) + , m_child_processes_inherit(false) { m_write_sp.reset(new File(fd, owns_fd)); m_read_sp.reset(new File(fd, false)); @@ -690,7 +692,7 @@ ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) { Socket *socket = nullptr; - Error error = Socket::UnixDomainAccept(socket_name, socket); + Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); @@ -702,7 +704,7 @@ ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) { Socket *socket = nullptr; - Error error = Socket::UnixDomainConnect(socket_name, socket); + Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); @@ -717,7 +719,7 @@ Socket *socket = nullptr; m_waiting_for_accept = true; - Error error = Socket::TcpListen(s, socket, &m_port_predicate); + Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); if (error_ptr) *error_ptr = error; if (error.Fail()) @@ -727,7 +729,7 @@ listening_socket_up.reset(socket); socket = nullptr; - error = listening_socket_up->BlockingAccept(s, socket); + error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket); listening_socket_up.reset(); if (error_ptr) *error_ptr = error; @@ -743,7 +745,7 @@ ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) { Socket *socket = nullptr; - Error error = Socket::TcpConnect(s, socket); + Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); @@ -756,7 +758,7 @@ { Socket *send_socket = nullptr; Socket *recv_socket = nullptr; - Error error = Socket::UdpConnect(s, send_socket, recv_socket); + Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(send_socket); @@ -778,3 +780,15 @@ } return bound_port; } + +bool +ConnectionFileDescriptor::GetChildProcessesInherit() const +{ + return m_child_processes_inherit; +} + +void +ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) +{ + m_child_processes_inherit = child_processes_inherit; +}