comment out unused parameters
[hiphop-php.git] / hphp / runtime / server / fastcgi / fastcgi-server.cpp
blob1ff564cb25a17aa12ef856df1f375d53c065937c
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/server/fastcgi/fastcgi-server.h"
19 #include "hphp/runtime/server/http-server.h"
21 namespace HPHP {
23 ////////////////////////////////////////////////////////////////////////////////
25 bool FastCGIAcceptor::canAccept(const folly::SocketAddress& /*address*/) {
26 // TODO: Support server IP whitelist.
27 auto const cons = m_server->getLibEventConnectionCount();
28 return (RuntimeOption::ServerConnectionLimit == 0 ||
29 cons < RuntimeOption::ServerConnectionLimit);
32 void FastCGIAcceptor::onNewConnection(
33 folly::AsyncTransportWrapper::UniquePtr sock,
34 const folly::SocketAddress* peerAddress,
35 const std::string& /*nextProtocolName*/,
36 SecureTransportType /*secureProtocolType*/,
37 const ::wangle::TransportInfo& /*tinfo*/) {
38 folly::SocketAddress localAddress;
39 try {
40 sock->getLocalAddress(&localAddress);
41 } catch (std::system_error& e) {
42 // If getSockName fails it's bad news; abort the connection
43 return;
46 // Will delete itself when it gets a closing callback
47 auto session = new FastCGISession(
48 m_server->getEventBaseManager()->getExistingEventBase(),
49 m_server->getDispatcher(),
50 std::move(sock),
51 localAddress,
52 *peerAddress
55 // NB: ~ManagedConnection will call removeConnection() before the session
56 // destroys itself.
57 Acceptor::addConnection(session);
60 void FastCGIAcceptor::onConnectionsDrained() {
61 m_server->onConnectionsDrained();
64 ////////////////////////////////////////////////////////////////////////////////
66 FastCGIServer::FastCGIServer(const std::string &address,
67 int port,
68 int workers,
69 bool useFileSocket)
70 : Server(address, port),
71 m_worker(&m_eventBaseManager),
72 m_dispatcher(workers,
73 RuntimeOption::ServerThreadDropCacheTimeoutSeconds,
74 RuntimeOption::ServerThreadDropStack,
75 this,
76 RuntimeOption::ServerThreadJobLIFOSwitchThreshold,
77 RuntimeOption::ServerThreadJobMaxQueuingMilliSeconds,
78 RequestPriority::k_numPriorities) {
79 folly::SocketAddress sock_addr;
80 if (useFileSocket) {
81 sock_addr.setFromPath(address);
82 } else if (address.empty()) {
83 sock_addr.setFromLocalPort(port);
84 } else {
85 sock_addr.setFromHostPort(address, port);
87 m_socketConfig.bindAddress = sock_addr;
88 m_socketConfig.acceptBacklog = RuntimeOption::ServerBacklog;
89 std::chrono::seconds timeout;
90 if (RuntimeOption::ConnectionTimeoutSeconds >= 0) {
91 timeout = std::chrono::seconds(RuntimeOption::ConnectionTimeoutSeconds);
92 } else {
93 // default to 2 minutes
94 timeout = std::chrono::seconds(120);
96 m_socketConfig.connectionIdleTimeout = timeout;
99 void FastCGIServer::start() {
100 // It's not safe to call this function more than once
101 m_socket.reset(new folly::AsyncServerSocket(m_worker.getEventBase()));
102 try {
103 m_socket->bind(m_socketConfig.bindAddress);
104 } catch (const std::system_error& ex) {
105 LOG(ERROR) << ex.what();
106 if (m_socketConfig.bindAddress.getFamily() == AF_UNIX) {
107 throw FailedToListenException(m_socketConfig.bindAddress.getPath());
109 throw FailedToListenException(m_socketConfig.bindAddress.getAddressStr(),
110 m_socketConfig.bindAddress.getPort());
112 if (m_socketConfig.bindAddress.getFamily() == AF_UNIX) {
113 auto path = m_socketConfig.bindAddress.getPath();
114 chmod(path.c_str(), 0760);
116 m_acceptor.reset(new FastCGIAcceptor(m_socketConfig, this));
117 m_acceptor->init(m_socket.get(), m_worker.getEventBase());
118 m_worker.getEventBase()->runInEventBaseThread([&] {
119 if (!m_socket) {
120 // Someone called stop before we got here. With the exception of a
121 // second call to start being made this should be safe as any place
122 // we mutate m_socket is done within the event base.
123 return;
125 m_socket->listen(m_socketConfig.acceptBacklog);
126 m_socket->startAccepting();
128 setStatus(RunStatus::RUNNING);
129 folly::AsyncTimeout::attachEventBase(m_worker.getEventBase());
130 m_worker.start();
131 m_dispatcher.start();
134 void FastCGIServer::waitForEnd() {
135 // When m_worker stops the server has stopped accepting new requests, there
136 // may be pedning vm jobs. wait() is always safe to call regardless of thread
137 m_worker.wait();
140 void FastCGIServer::stop() {
141 if (getStatus() != RunStatus::RUNNING) return; // nothing to do
143 setStatus(RunStatus::STOPPING);
144 HttpServer::MarkShutdownStat(ShutdownEvent::SHUTDOWN_DRAIN_READS);
146 m_worker.getEventBase()->runInEventBaseThread([&] {
147 // Shutdown the server socket. Unfortunately, we will drop all unaccepted
148 // connections; there is no way to do a partial shutdown of a server socket
149 m_socket->stopAccepting();
151 if (RuntimeOption::ServerGracefulShutdownWait > 0) {
152 // Gracefully drain any incomplete requests. We cannot go offline until
153 // they are finished as we own their dispatcher and event base.
154 if (m_acceptor) {
155 m_acceptor->drainAllConnections();
158 std::chrono::seconds s(RuntimeOption::ServerGracefulShutdownWait);
159 std::chrono::milliseconds m(s);
160 scheduleTimeout(m);
161 } else {
162 // Drop all connections. We cannot shutdown until they stop because we
163 // own their dispatcher and event base.
164 if (m_acceptor) {
165 m_acceptor->forceStop();
168 terminateServer();
173 void FastCGIServer::onConnectionsDrained() {
174 // NOTE: called from FastCGIAcceptor::onConnectionsDrained()
175 cancelTimeout();
176 terminateServer();
179 void FastCGIServer::timeoutExpired() noexcept {
180 // Acceptor failed to drain connections on time; drop them so that we can
181 // shutdown.
182 if (m_acceptor) {
183 m_acceptor->forceStop();
186 terminateServer();
189 void FastCGIServer::terminateServer() {
190 if (getStatus() != RunStatus::STOPPING) {
191 setStatus(RunStatus::STOPPING);
193 // Wait for the server socket thread to stop running
194 m_worker.stopWhenIdle();
196 HttpServer::MarkShutdownStat(ShutdownEvent::SHUTDOWN_DRAIN_DISPATCHER);
197 // Wait for VMs to shutdown
198 m_dispatcher.stop();
200 setStatus(RunStatus::STOPPED);
201 HttpServer::MarkShutdownStat(ShutdownEvent::SHUTDOWN_DONE);
203 // Notify HttpServer that we've shutdown
204 for (auto listener: m_listeners) {
205 listener->serverStopped(this);
209 ////////////////////////////////////////////////////////////////////////////////