Support for UNIX sockets
Add a new config param, Server.FileSocket. When Server.FileSocket is set it will be used inplace of a network socket for the primary server. This uses a new parameter to ServerOptions, m_useFileSocket, to toggle between treating the address as a socket path or a network address. To initialize a socket connection thrift expects the socket file to not exist. To support this the 'something nice' retry in startServer will unlink an existing socket only if fuser claims it is unused. Server.EvilShutdown enables unlinking the socket regardless of current users. Closes #1594 Reviewed By: @ptarjan Differential Revision: D1135876 Pulled By: @sgolemon
Esse commit está contido em:
@@ -107,6 +107,7 @@ std::string RuntimeOption::Host;
|
||||
std::string RuntimeOption::DefaultServerNameSuffix;
|
||||
std::string RuntimeOption::ServerType = "libevent";
|
||||
std::string RuntimeOption::ServerIP;
|
||||
std::string RuntimeOption::ServerFileSocket;
|
||||
std::string RuntimeOption::ServerPrimaryIP;
|
||||
int RuntimeOption::ServerPort;
|
||||
int RuntimeOption::ServerPortFd = -1;
|
||||
@@ -721,6 +722,7 @@ void RuntimeOption::Load(Hdf &config,
|
||||
DefaultServerNameSuffix = server["DefaultServerNameSuffix"].getString();
|
||||
ServerType = server["Type"].getString(ServerType);
|
||||
ServerIP = server["IP"].getString();
|
||||
ServerFileSocket = server["FileSocket"].getString();
|
||||
ServerPrimaryIP = Util::GetPrimaryIP();
|
||||
ServerPort = server["Port"].getUInt16(80);
|
||||
ServerBacklog = server["Backlog"].getInt16(128);
|
||||
|
||||
@@ -109,6 +109,7 @@ public:
|
||||
static std::string DefaultServerNameSuffix;
|
||||
static std::string ServerType;
|
||||
static std::string ServerIP;
|
||||
static std::string ServerFileSocket;
|
||||
static std::string ServerPrimaryIP;
|
||||
static int ServerPort;
|
||||
static int ServerPortFd;
|
||||
|
||||
@@ -25,7 +25,8 @@ public:
|
||||
virtual ServerPtr createServer(const ServerOptions& options) override {
|
||||
return std::make_shared<FastCGIServer>(options.m_address,
|
||||
options.m_port,
|
||||
options.m_numThreads);
|
||||
options.m_numThreads,
|
||||
options.m_useFileSocket);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -183,7 +183,8 @@ void FastCGIConnection::handleRequest(int transport_id) {
|
||||
|
||||
FastCGIServer::FastCGIServer(const std::string &address,
|
||||
int port,
|
||||
int workers)
|
||||
int workers,
|
||||
bool useFileSocket)
|
||||
: Server(address, port, workers),
|
||||
m_worker(&m_eventBaseManager),
|
||||
m_dispatcher(workers,
|
||||
@@ -195,7 +196,9 @@ FastCGIServer::FastCGIServer(const std::string &address,
|
||||
RuntimeOption::ServerThreadJobMaxQueuingMilliSeconds,
|
||||
RequestPriority::k_numPriorities) {
|
||||
TSocketAddress sock_addr;
|
||||
if (address.empty()) {
|
||||
if (useFileSocket) {
|
||||
sock_addr.setFromPath(address);
|
||||
} else if (address.empty()) {
|
||||
sock_addr.setFromLocalPort(port);
|
||||
} else {
|
||||
sock_addr.setFromHostPort(address, port);
|
||||
@@ -226,8 +229,12 @@ void FastCGIServer::start() {
|
||||
m_socket->bind(m_socketConfig.getAddress());
|
||||
} catch (const apache::thrift::transport::TTransportException& ex) {
|
||||
LOG(ERROR) << ex.what();
|
||||
throw FailedToListenException(m_socketConfig.getAddress().getAddressStr(),
|
||||
m_socketConfig.getAddress().getPort());
|
||||
if (m_socketConfig.getAddress().getFamily() == AF_UNIX) {
|
||||
throw FailedToListenException(m_socketConfig.getAddress().getPath());
|
||||
} else {
|
||||
throw FailedToListenException(m_socketConfig.getAddress().getAddressStr(),
|
||||
m_socketConfig.getAddress().getPort());
|
||||
}
|
||||
}
|
||||
m_acceptor.reset(new FastCGIAcceptor(m_socketConfig, this));
|
||||
m_acceptor->init(m_socket.get(), m_worker.getEventBase());
|
||||
|
||||
@@ -128,7 +128,8 @@ class FastCGIServer : public Server,
|
||||
public:
|
||||
FastCGIServer(const std::string &address,
|
||||
int port,
|
||||
int workers);
|
||||
int workers,
|
||||
bool useFileSocket);
|
||||
~FastCGIServer() {
|
||||
if (!m_done) {
|
||||
waitForEnd();
|
||||
|
||||
@@ -77,9 +77,11 @@ HttpServer::HttpServer()
|
||||
|
||||
auto serverFactory = ServerFactoryRegistry::getInstance()->getFactory
|
||||
(RuntimeOption::ServerType);
|
||||
ServerOptions options
|
||||
(RuntimeOption::ServerIP, RuntimeOption::ServerPort,
|
||||
startingThreadCount);
|
||||
const std::string address = RuntimeOption::ServerFileSocket.empty()
|
||||
? RuntimeOption::ServerIP : RuntimeOption::ServerFileSocket;
|
||||
ServerOptions options(
|
||||
address, RuntimeOption::ServerPort, startingThreadCount);
|
||||
options.m_useFileSocket = !RuntimeOption::ServerFileSocket.empty();
|
||||
options.m_serverFD = RuntimeOption::ServerPortFd;
|
||||
options.m_sslFD = RuntimeOption::SSLPortFd;
|
||||
options.m_takeoverFilename = RuntimeOption::TakeoverFilename;
|
||||
@@ -498,7 +500,12 @@ bool HttpServer::startServer(bool pageServer) {
|
||||
}
|
||||
|
||||
if (errno == EACCES) {
|
||||
Logger::Error("Permission denied listening on port %d", port);
|
||||
if (pageServer && !RuntimeOption::ServerFileSocket.empty()) {
|
||||
Logger::Error("Permission denied opening socket at %s",
|
||||
RuntimeOption::ServerFileSocket.c_str());
|
||||
} else {
|
||||
Logger::Error("Permission denied listening on port %d", port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -511,6 +518,22 @@ bool HttpServer::startServer(bool pageServer) {
|
||||
StringBuffer response;
|
||||
http.get(url.c_str(), response);
|
||||
|
||||
if (pageServer && !RuntimeOption::ServerFileSocket.empty()) {
|
||||
if (i == 0) {
|
||||
Logger::Info("Unlinking unused socket at %s",
|
||||
RuntimeOption::ServerFileSocket.c_str());
|
||||
}
|
||||
struct stat stat_buf;
|
||||
if (stat(RuntimeOption::ServerFileSocket.c_str(), &stat_buf) == 0
|
||||
&& S_ISSOCK(stat_buf.st_mode)) {
|
||||
std::string cmd = "bash -c '! fuser ";
|
||||
cmd += RuntimeOption::ServerFileSocket;
|
||||
cmd += "'";
|
||||
if (Util::ssystem(cmd.c_str()) == 0) {
|
||||
unlink(RuntimeOption::ServerFileSocket.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
@@ -546,15 +569,27 @@ bool HttpServer::startServer(bool pageServer) {
|
||||
}
|
||||
return true;
|
||||
} catch (FailedToListenException &e) {
|
||||
if (i == 0) {
|
||||
Logger::Info("killing anything listening on port %d", port);
|
||||
if (pageServer && !RuntimeOption::ServerFileSocket.empty()) {
|
||||
if (i == 0) {
|
||||
Logger::Info("unlinking socket at %s",
|
||||
RuntimeOption::ServerFileSocket.c_str());
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (stat(RuntimeOption::ServerFileSocket.c_str(), &stat_buf) == 0
|
||||
&& S_ISSOCK(stat_buf.st_mode)) {
|
||||
unlink(RuntimeOption::ServerFileSocket.c_str());
|
||||
}
|
||||
} else {
|
||||
if (i == 0) {
|
||||
Logger::Info("killing anything listening on port %d", port);
|
||||
}
|
||||
|
||||
std::string cmd = "lsof -t -i :";
|
||||
cmd += lexical_cast<std::string>(port);
|
||||
cmd += " | xargs kill -9";
|
||||
Util::ssystem(cmd.c_str());
|
||||
}
|
||||
|
||||
std::string cmd = "lsof -t -i :";
|
||||
cmd += lexical_cast<std::string>(port);
|
||||
cmd += " | xargs kill -9";
|
||||
Util::ssystem(cmd.c_str());
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,8 @@ public:
|
||||
m_numThreads(numThreads),
|
||||
m_serverFD(-1),
|
||||
m_sslFD(-1),
|
||||
m_takeoverFilename() {
|
||||
m_takeoverFilename(),
|
||||
m_useFileSocket(false) {
|
||||
}
|
||||
|
||||
std::string m_address;
|
||||
@@ -274,6 +275,7 @@ public:
|
||||
int m_serverFD;
|
||||
int m_sslFD;
|
||||
std::string m_takeoverFilename;
|
||||
bool m_useFileSocket;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -327,6 +329,9 @@ public:
|
||||
|
||||
class FailedToListenException : public ServerException {
|
||||
public:
|
||||
explicit FailedToListenException(const std::string &addr)
|
||||
: ServerException("Failed to listen to unix socket at %s", addr.c_str()) {
|
||||
}
|
||||
FailedToListenException(const std::string &addr, int port)
|
||||
: ServerException("Failed to listen on %s:%d", addr.c_str(), port) {
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário