Commit f5cc18a3 authored by Orvid King's avatar Orvid King Committed by Facebook Github Bot

Support NetworkSocket in ShutdownSocketSet

Summary: More places supporting NetworkSocket.

Reviewed By: yfeldblum

Differential Revision: D12818369

fbshipit-source-id: 6ee0ce2dde3283ea7fd8f657329dc55c78c90714
parent d580d889
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/net/NetOps.h>
#include <folly/portability/Sockets.h> #include <folly/portability/Sockets.h>
namespace folly { namespace folly {
...@@ -32,27 +33,27 @@ ShutdownSocketSet::ShutdownSocketSet(int maxFd) ...@@ -32,27 +33,27 @@ ShutdownSocketSet::ShutdownSocketSet(int maxFd)
folly::checkedCalloc(size_t(maxFd), sizeof(std::atomic<uint8_t>)))), folly::checkedCalloc(size_t(maxFd), sizeof(std::atomic<uint8_t>)))),
nullFile_("/dev/null", O_RDWR) {} nullFile_("/dev/null", O_RDWR) {}
void ShutdownSocketSet::add(int fd) { void ShutdownSocketSet::add(NetworkSocket fd) {
// Silently ignore any fds >= maxFd_, very unlikely // Silently ignore any fds >= maxFd_, very unlikely
DCHECK_GE(fd, 0); DCHECK_NE(fd, NetworkSocket());
if (fd >= maxFd_) { if (fd.data >= maxFd_) {
return; return;
} }
auto& sref = data_[size_t(fd)]; auto& sref = data_[size_t(fd.data)];
uint8_t prevState = FREE; uint8_t prevState = FREE;
CHECK(sref.compare_exchange_strong( CHECK(sref.compare_exchange_strong(
prevState, IN_USE, std::memory_order_relaxed)) prevState, IN_USE, std::memory_order_relaxed))
<< "Invalid prev state for fd " << fd << ": " << int(prevState); << "Invalid prev state for fd " << fd << ": " << int(prevState);
} }
void ShutdownSocketSet::remove(int fd) { void ShutdownSocketSet::remove(NetworkSocket fd) {
DCHECK_GE(fd, 0); DCHECK_NE(fd, NetworkSocket());
if (fd >= maxFd_) { if (fd.data >= maxFd_) {
return; return;
} }
auto& sref = data_[size_t(fd)]; auto& sref = data_[size_t(fd.data)];
uint8_t prevState = 0; uint8_t prevState = 0;
prevState = sref.load(std::memory_order_relaxed); prevState = sref.load(std::memory_order_relaxed);
...@@ -70,13 +71,13 @@ void ShutdownSocketSet::remove(int fd) { ...@@ -70,13 +71,13 @@ void ShutdownSocketSet::remove(int fd) {
!sref.compare_exchange_weak(prevState, FREE, std::memory_order_relaxed)); !sref.compare_exchange_weak(prevState, FREE, std::memory_order_relaxed));
} }
int ShutdownSocketSet::close(int fd) { int ShutdownSocketSet::close(NetworkSocket fd) {
DCHECK_GE(fd, 0); DCHECK_NE(fd, NetworkSocket());
if (fd >= maxFd_) { if (fd.data >= maxFd_) {
return folly::closeNoInt(fd); return folly::closeNoInt(fd);
} }
auto& sref = data_[size_t(fd)]; auto& sref = data_[size_t(fd.data)];
uint8_t prevState = sref.load(std::memory_order_relaxed); uint8_t prevState = sref.load(std::memory_order_relaxed);
uint8_t newState = 0; uint8_t newState = 0;
...@@ -99,14 +100,14 @@ int ShutdownSocketSet::close(int fd) { ...@@ -99,14 +100,14 @@ int ShutdownSocketSet::close(int fd) {
return newState == FREE ? folly::closeNoInt(fd) : 0; return newState == FREE ? folly::closeNoInt(fd) : 0;
} }
void ShutdownSocketSet::shutdown(int fd, bool abortive) { void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) {
DCHECK_GE(fd, 0); DCHECK_NE(fd, NetworkSocket());
if (fd >= maxFd_) { if (fd.data >= maxFd_) {
doShutdown(fd, abortive); doShutdown(fd, abortive);
return; return;
} }
auto& sref = data_[size_t(fd)]; auto& sref = data_[size_t(fd.data)];
uint8_t prevState = IN_USE; uint8_t prevState = IN_USE;
if (!sref.compare_exchange_strong( if (!sref.compare_exchange_strong(
prevState, IN_SHUTDOWN, std::memory_order_relaxed)) { prevState, IN_SHUTDOWN, std::memory_order_relaxed)) {
...@@ -135,12 +136,14 @@ void ShutdownSocketSet::shutdownAll(bool abortive) { ...@@ -135,12 +136,14 @@ void ShutdownSocketSet::shutdownAll(bool abortive) {
for (int i = 0; i < maxFd_; ++i) { for (int i = 0; i < maxFd_; ++i) {
auto& sref = data_[size_t(i)]; auto& sref = data_[size_t(i)];
if (sref.load(std::memory_order_relaxed) == IN_USE) { if (sref.load(std::memory_order_relaxed) == IN_USE) {
shutdown(i, abortive); shutdown(
NetworkSocket(static_cast<NetworkSocket::native_handle_type>(i)),
abortive);
} }
} }
} }
void ShutdownSocketSet::doShutdown(int fd, bool abortive) { void ShutdownSocketSet::doShutdown(NetworkSocket fd, bool abortive) {
// shutdown() the socket first, to awaken any threads blocked on the fd // shutdown() the socket first, to awaken any threads blocked on the fd
// (subsequent IO will fail because it's been shutdown); close()ing the // (subsequent IO will fail because it's been shutdown); close()ing the
// socket does not wake up blockers, see // socket does not wake up blockers, see
...@@ -152,17 +155,23 @@ void ShutdownSocketSet::doShutdown(int fd, bool abortive) { ...@@ -152,17 +155,23 @@ void ShutdownSocketSet::doShutdown(int fd, bool abortive) {
// close. // close.
if (abortive) { if (abortive) {
struct linger l = {1, 0}; struct linger l = {1, 0};
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) != 0) { if (netops::setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) != 0) {
// Probably not a socket, ignore. // Probably not a socket, ignore.
return; return;
} }
} }
// Note that this can be ignored without breaking anything due to the
// fact the file descriptor will eventually be closed, so on Windows
// all of the socket resources will just stick around longer than they
// do on posix-like systems.
#ifndef _WIN32
// We can't close() the socket, as that would be dangerous; a new file // We can't close() the socket, as that would be dangerous; a new file
// could be opened and get the same file descriptor, and then code assuming // could be opened and get the same file descriptor, and then code assuming
// the old fd would do IO in the wrong place. We'll (atomically) dup2 // the old fd would do IO in the wrong place. We'll (atomically) dup2
// /dev/null onto the fd instead. // /dev/null onto the fd instead.
folly::dup2NoInt(nullFile_.fd(), fd); folly::dup2NoInt(nullFile_.fd(), fd.toFd());
#endif
} }
} // namespace folly } // namespace folly
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <folly/File.h> #include <folly/File.h>
#include <folly/net/NetworkSocket.h>
namespace folly { namespace folly {
...@@ -45,7 +46,10 @@ class ShutdownSocketSet : private boost::noncopyable { ...@@ -45,7 +46,10 @@ class ShutdownSocketSet : private boost::noncopyable {
* ShutdownSocketSet::close (which will, as a side effect, also handle EINTR * ShutdownSocketSet::close (which will, as a side effect, also handle EINTR
* properly) and not by calling close() on the file descriptor. * properly) and not by calling close() on the file descriptor.
*/ */
void add(int fd); void add(NetworkSocket fd);
void add(int fd) {
add(NetworkSocket::fromFd(fd));
}
/** /**
* Remove a socket from the list of sockets managed by ShutdownSocketSet. * Remove a socket from the list of sockets managed by ShutdownSocketSet.
...@@ -53,13 +57,19 @@ class ShutdownSocketSet : private boost::noncopyable { ...@@ -53,13 +57,19 @@ class ShutdownSocketSet : private boost::noncopyable {
* sleep()-ing) in the extremely rare case that the fd is currently * sleep()-ing) in the extremely rare case that the fd is currently
* being shutdown(). * being shutdown().
*/ */
void remove(int fd); void remove(NetworkSocket fd);
void remove(int fd) {
remove(NetworkSocket::fromFd(fd));
}
/** /**
* Close a socket managed by ShutdownSocketSet. Returns the same return code * Close a socket managed by ShutdownSocketSet. Returns the same return code
* as ::close() (and sets errno accordingly). * as ::close() (and sets errno accordingly).
*/ */
int close(int fd); int close(NetworkSocket fd);
int close(int fd) {
return close(NetworkSocket::fromFd(fd));
}
/** /**
* Shut down a socket. If abortive is true, we perform an abortive * Shut down a socket. If abortive is true, we perform an abortive
...@@ -70,7 +80,10 @@ class ShutdownSocketSet : private boost::noncopyable { ...@@ -70,7 +80,10 @@ class ShutdownSocketSet : private boost::noncopyable {
* read() and write() operations to the socket will fail. During normal * read() and write() operations to the socket will fail. During normal
* operation, just call ::shutdown() on the socket. * operation, just call ::shutdown() on the socket.
*/ */
void shutdown(int fd, bool abortive = false); void shutdown(NetworkSocket fd, bool abortive = false);
void shutdown(int fd, bool abortive = false) {
shutdown(NetworkSocket::fromFd(fd), abortive);
}
/** /**
* Immediate shutdown of all connections. This is a hard-hitting hammer; * Immediate shutdown of all connections. This is a hard-hitting hammer;
...@@ -95,7 +108,7 @@ class ShutdownSocketSet : private boost::noncopyable { ...@@ -95,7 +108,7 @@ class ShutdownSocketSet : private boost::noncopyable {
void shutdownAll(bool abortive = false); void shutdownAll(bool abortive = false);
private: private:
void doShutdown(int fd, bool abortive); void doShutdown(NetworkSocket fd, bool abortive);
// State transitions: // State transitions:
// add(): // add():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment