Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(605)

Unified Diff: net/tools/flip_server/flip_in_mem_edsm_server.cc

Issue 6332010: Memory leak fix, log file reopen, remote ip fix, connection idle timeout,... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/tools/flip_server/flip_config.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/flip_server/flip_in_mem_edsm_server.cc
===================================================================
--- net/tools/flip_server/flip_in_mem_edsm_server.cc (revision 71892)
+++ net/tools/flip_server/flip_in_mem_edsm_server.cc (working copy)
@@ -6,6 +6,8 @@
#include <netinet/tcp.h> // For TCP_NODELAY
#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
@@ -48,6 +50,7 @@
using std::string;
using std::vector;
using std::cout;
+using std::cerr;
////////////////////////////////////////////////////////////////////////////////
@@ -61,6 +64,8 @@
#define SSL_CTX_DEFAULT_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
+#define PIDFILE "/var/run/flip-server.pid"
+
// If true, then disables the nagle algorithm);
bool FLAGS_disable_nagle = true;
@@ -289,13 +294,26 @@
bool delete_when_done;
size_t index;
DataFrame() : data(NULL), size(0), delete_when_done(false), index(0) {}
- void MaybeDelete() {
+ virtual void MaybeDelete() {
if (delete_when_done) {
delete[] data;
}
}
+ virtual ~DataFrame() {
+ MaybeDelete();
+ }
};
+class SpdyFrameDataFrame : public DataFrame {
+ public:
+ SpdyFrame* frame;
+ virtual void MaybeDelete() {
+ if (delete_when_done) {
+ delete frame;
+ }
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
class StoreBodyAndHeadersVisitor: public BalsaVisitorInterface {
@@ -698,6 +716,7 @@
int fd,
string server_ip,
string server_port,
+ string remote_ip,
bool use_ssl) = 0;
virtual size_t ProcessReadInput(const char* data, size_t len) = 0;
virtual size_t ProcessWriteInput(const char* data, size_t len) = 0;
@@ -741,7 +760,7 @@
class HttpSM;
class SMConnection;
-typedef list<DataFrame> OutputList;
+typedef list<DataFrame*> OutputList;
class SMConnectionPoolInterface {
public:
@@ -796,7 +815,8 @@
sm_interface_(NULL),
log_prefix_(log_prefix),
max_bytes_sent_per_dowrite_(4096),
- ssl_(NULL)
+ ssl_(NULL),
+ last_read_time_(0)
{}
int fd_;
@@ -828,6 +848,7 @@
SSL* ssl_;
public:
+ time_t last_read_time_;
string server_ip_;
string server_port_;
@@ -839,10 +860,10 @@
<< "Setting ready to send: EPOLLIN | EPOLLOUT";
epoll_server_->SetFDReady(fd_, EPOLLIN | EPOLLOUT);
}
- void EnqueueDataFrame(const DataFrame& df) {
+ void EnqueueDataFrame(DataFrame* df) {
output_list_.push_back(df);
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "EnqueueDataFrame: "
- << "size = " << df.size << ": Setting FD ready.";
+ << "size = " << df->size << ": Setting FD ready.";
ReadyToSend();
}
int fd() { return fd_; }
@@ -871,12 +892,15 @@
int fd,
string server_ip,
string server_port,
+ string remote_ip,
bool use_ssl) {
if (initialized_) {
LOG(FATAL) << "Attempted to initialize already initialized server";
return;
}
+ client_ip_ = remote_ip;
+
if (fd == -1) {
// If fd == -1, then we are initializing a new connection that will
// connect to the backend.
@@ -921,23 +945,12 @@
}
fd_ = fd;
- struct sockaddr sock_addr;
- socklen_t addr_size = sizeof(sock_addr);
- addr_size = sizeof(sock_addr);
- int res = getsockname(fd_, &sock_addr, &addr_size);
- if (res < 0) {
- LOG(ERROR) << "Could not get socket address for fd " << fd_
- << ": getsockname: " << strerror(errno);
- } else {
- struct sockaddr_in *sock_addr_in = (struct sockaddr_in *)&sock_addr;
- char ip[16];
- snprintf(ip, sizeof(ip), "%d.%d.%d.%d",
- IPV4_PRINTABLE_FORMAT(sock_addr_in->sin_addr.s_addr));
- client_ip_ = ip;
- }
}
registered_in_epoll_server_ = false;
+ // Set the last read time here as the idle checker will start from
+ // now.
+ last_read_time_ = time(NULL);
initialized_ = true;
connection_pool_ = connection_pool;
@@ -991,6 +1004,12 @@
if (rv != chunksize)
break; // If we couldn't write everything, we're implicitly stalled
}
+ if (!(flags & MSG_MORE)) {
+ int state = 0;
+ setsockopt( fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
+ state = 1;
+ setsockopt( fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
+ }
} else {
bytes_written = send(fd_, data, len, flags);
}
@@ -1019,7 +1038,7 @@
}
void Cleanup(const char* cleanup) {
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Cleanup";
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Cleanup: " << cleanup;
if (!initialized_) {
return;
}
@@ -1030,6 +1049,7 @@
if (sm_interface_) {
sm_interface_->ResetForNewConnection();
}
+ last_read_time_ = 0;
}
private:
@@ -1132,6 +1152,7 @@
} else if (bytes_read > 0) {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "read " << bytes_read
<< " bytes";
+ last_read_time_ = time(NULL);
if (!protocol_detected_) {
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
// Http Server
@@ -1303,11 +1324,11 @@
if (sm_interface_ && output_list_.size() < 2) {
sm_interface_->GetOutput();
}
- DataFrame& data_frame = output_list_.front();
- const char* bytes = data_frame.data;
- int size = data_frame.size;
- bytes += data_frame.index;
- size -= data_frame.index;
+ DataFrame* data_frame = output_list_.front();
+ const char* bytes = data_frame->data;
+ int size = data_frame->size;
+ bytes += data_frame->index;
+ size -= data_frame->index;
DCHECK_GE(size, 0);
if (size <= 0) {
// Empty data frame. Indicates end of data from client.
@@ -1315,8 +1336,8 @@
int state = 0;
VLOG(2) << log_prefix_ << "Empty data frame, uncorking socket.";
setsockopt( fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
- data_frame.MaybeDelete();
output_list_.pop_front();
+ delete data_frame;
continue;
}
@@ -1349,7 +1370,7 @@
} else if (bytes_written > 0) {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Wrote: "
<< bytes_written << " bytes";
- data_frame.index += bytes_written;
+ data_frame->index += bytes_written;
bytes_sent += bytes_written;
continue;
} else if (bytes_written == -2) {
@@ -1384,6 +1405,7 @@
PrintSslError();
SSL_free(ssl_);
PrintSslError();
+ ssl_ = NULL;
}
if (registered_in_epoll_server_) {
epoll_server_->UnregisterFD(fd_);
@@ -1398,6 +1420,12 @@
initialized_ = false;
protocol_detected_ = false;
events_ = 0;
+ for (list<DataFrame*>::iterator i =
+ output_list_.begin();
+ i != output_list_.end();
+ ++i) {
+ delete *i;
+ }
output_list_.clear();
}
@@ -1639,12 +1667,13 @@
int fd,
string server_ip,
string server_port,
+ string remote_ip,
bool use_ssl) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT
<< "SpdySM: Initializing server connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
epoll_server, fd, server_ip, server_port,
- use_ssl);
+ remote_ip, use_ssl);
}
private:
@@ -1690,13 +1719,13 @@
sm_http_interface->InitSMInterface(this, server_idx);
sm_http_interface->InitSMConnection(NULL, sm_http_interface,
epoll_server_, -1,
- server_ip, server_port, false);
+ server_ip, server_port, "", false);
return sm_http_interface;
}
int SpdyHandleNewStream(const SpdyControlFrame* frame,
- string *http_data,
+ string &http_data,
bool *is_https_scheme)
{
bool parsed_headers = false;
@@ -1743,21 +1772,21 @@
filename);
} else {
SpdyHeaderBlock::iterator version = headers.find("version");
- *http_data += method->second + " " + uri + " " + version->second + "\r\n";
+ http_data += method->second + " " + uri + " " + version->second + "\r\n";
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " "
<< uri << " " << version->second;
for (SpdyHeaderBlock::iterator i = headers.begin();
i != headers.end(); ++i) {
- *http_data += i->first + ": " + i->second + "\r\n";
+ http_data += i->first + ": " + i->second + "\r\n";
VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":"
<< i->second.c_str();
}
if (g_proxy_config.forward_ip_header_enabled_) {
// X-Client-Cluster-IP header
- *http_data += g_proxy_config.forward_ip_header_ + ": " +
+ http_data += g_proxy_config.forward_ip_header_ + ": " +
connection_->client_ip() + "\r\n";
}
- *http_data += "\r\n";
+ http_data += "\r\n";
}
VLOG(3) << ACCEPTOR_CLIENT_IDENT << "SpdySM: HTTP Request:\n" << http_data;
@@ -1775,7 +1804,7 @@
string http_data;
bool is_https_scheme;
- int ret = SpdyHandleNewStream(frame, &http_data, &is_https_scheme);
+ int ret = SpdyHandleNewStream(frame, http_data, &is_https_scheme);
if (!ret) {
LOG(ERROR) << "SpdySM: Could not convert spdy into http.";
break;
@@ -1879,8 +1908,7 @@
// some logic review and method renaming is probably in order.
void Cleanup() {}
- // Send a settings frame and possibly some NOOP packets to force
- // opening of cwnd
+ // Send a settings frame
int PostAcceptHook() {
ssize_t bytes_written;
spdy::SpdySettings settings;
@@ -2042,11 +2070,12 @@
SpdySynStreamControlFrame* fsrcf =
spdy_framer_->CreateSynStream(stream_id, 0, 0, CONTROL_FLAG_NONE, true,
&block);
- DataFrame df;
- df.size = fsrcf->length() + SpdyFrame::size();
- size_t df_size = df.size;
- df.data = fsrcf->data();
- df.delete_when_done = true;
+ SpdyFrameDataFrame* df = new SpdyFrameDataFrame;
+ df->size = fsrcf->length() + SpdyFrame::size();
+ size_t df_size = df->size;
+ df->data = fsrcf->data();
+ df->frame = fsrcf;
+ df->delete_when_done = true;
EnqueueDataFrame(df);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynStreamheader "
@@ -2063,11 +2092,12 @@
SpdySynReplyControlFrame* fsrcf =
spdy_framer_->CreateSynReply(stream_id, CONTROL_FLAG_NONE, true, &block);
- DataFrame df;
- df.size = fsrcf->length() + SpdyFrame::size();
- size_t df_size = df.size;
- df.data = fsrcf->data();
- df.delete_when_done = true;
+ SpdyFrameDataFrame* df = new SpdyFrameDataFrame;
+ df->size = fsrcf->length() + SpdyFrame::size();
+ size_t df_size = df->size;
+ df->data = fsrcf->data();
+ df->frame = fsrcf;
+ df->delete_when_done = true;
EnqueueDataFrame(df);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynReplyheader "
@@ -2084,14 +2114,13 @@
// TODO(mbelshe): We can't compress here - before going into the
// priority queue. Compression needs to be done
// with late binding.
-
if (len == 0) {
SpdyDataFrame* fdf = spdy_framer_->CreateDataFrame(stream_id, data, len,
flags);
- DataFrame df;
- df.size = fdf->length() + SpdyFrame::size();
- df.data = fdf->data();
- df.delete_when_done = true;
+ SpdyFrameDataFrame* df = new SpdyFrameDataFrame;
+ df->size = fdf->length() + SpdyFrame::size();
+ df->data = fdf->data();
+ df->delete_when_done = true;
EnqueueDataFrame(df);
return;
}
@@ -2109,10 +2138,10 @@
SpdyDataFrame* fdf = spdy_framer_->CreateDataFrame(stream_id, data, size,
chunk_flags);
- DataFrame df;
- df.size = fdf->length() + SpdyFrame::size();
- df.data = fdf->data();
- df.delete_when_done = true;
+ SpdyFrameDataFrame* df = new SpdyFrameDataFrame;
+ df->size = fdf->length() + SpdyFrame::size();
+ df->data = fdf->data();
+ df->delete_when_done = true;
EnqueueDataFrame(df);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending data frame "
@@ -2124,7 +2153,7 @@
}
}
- void EnqueueDataFrame(const DataFrame& df) {
+ void EnqueueDataFrame(DataFrame* df) {
connection_->EnqueueDataFrame(df);
}
@@ -2323,13 +2352,14 @@
int fd,
string server_ip,
string server_port,
+ string remote_ip,
bool use_ssl)
{
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
<< "connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
epoll_server, fd, server_ip, server_port,
- use_ssl);
+ remote_ip, use_ssl);
}
size_t ProcessReadInput(const char* data, size_t len) {
@@ -2343,10 +2373,10 @@
<< len << ": stream " << stream_id_;
char * dataPtr = new char[len];
memcpy(dataPtr, data, len);
- DataFrame data_frame;
- data_frame.data = (const char *)dataPtr;
- data_frame.size = len;
- data_frame.delete_when_done = true;
+ DataFrame* data_frame = new DataFrame;
+ data_frame->data = (const char *)dataPtr;
+ data_frame->size = len;
+ data_frame->delete_when_done = true;
connection_->EnqueueDataFrame(data_frame);
return len;
}
@@ -2450,10 +2480,10 @@
private:
void SendEOFImpl(uint32 stream_id) {
- DataFrame df;
- df.data = "0\r\n\r\n";
- df.size = 5;
- df.delete_when_done = false;
+ DataFrame* df = new DataFrame;
+ df->data = "0\r\n\r\n";
+ df->size = 5;
+ df->delete_when_done = false;
EnqueueDataFrame(df);
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
Reset();
@@ -2485,15 +2515,15 @@
size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
SimpleBuffer sb;
headers.WriteHeaderAndEndingToBuffer(&sb);
- DataFrame df;
- df.size = sb.ReadableBytes();
- char* buffer = new char[df.size];
- df.data = buffer;
- df.delete_when_done = true;
- sb.Read(buffer, df.size);
+ DataFrame* df = new DataFrame;
+ df->size = sb.ReadableBytes();
+ char* buffer = new char[df->size];
+ df->data = buffer;
+ df->delete_when_done = true;
+ sb.Read(buffer, df->size);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
<< stream_id_;
- size_t df_size = df.size;
+ size_t df_size = df->size;
EnqueueDataFrame(df);
return df_size;
}
@@ -2501,15 +2531,15 @@
size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) {
SimpleBuffer sb;
headers.WriteHeaderAndEndingToBuffer(&sb);
- DataFrame df;
- df.size = sb.ReadableBytes();
- char* buffer = new char[df.size];
- df.data = buffer;
- df.delete_when_done = true;
- sb.Read(buffer, df.size);
+ DataFrame* df = new DataFrame;
+ df->size = sb.ReadableBytes();
+ char* buffer = new char[df->size];
+ df->data = buffer;
+ df->delete_when_done = true;
+ sb.Read(buffer, df->size);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
<< stream_id_;
- size_t df_size = df.size;
+ size_t df_size = df->size;
EnqueueDataFrame(df);
return df_size;
}
@@ -2519,18 +2549,18 @@
char chunk_buf[128];
snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
string chunk_description(chunk_buf);
- DataFrame df;
- df.size = chunk_description.size() + len + 2;
- char* buffer = new char[df.size];
- df.data = buffer;
- df.delete_when_done = true;
+ DataFrame* df = new DataFrame;
+ df->size = chunk_description.size() + len + 2;
+ char* buffer = new char[df->size];
+ df->data = buffer;
+ df->delete_when_done = true;
memcpy(buffer, chunk_description.data(), chunk_description.size());
memcpy(buffer + chunk_description.size(), data, len);
memcpy(buffer + chunk_description.size() + len, "\r\n", 2);
EnqueueDataFrame(df);
}
- void EnqueueDataFrame(const DataFrame& df) {
+ void EnqueueDataFrame(DataFrame* df) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream "
<< stream_id_;
connection_->EnqueueDataFrame(df);
@@ -2610,13 +2640,14 @@
int fd,
string server_ip,
string server_port,
+ string remote_ip,
bool use_ssl)
{
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
<< "connection.";
connection_->InitSMConnection(connection_pool, sm_interface,
epoll_server, fd, server_ip,
- server_port, use_ssl);
+ server_port, remote_ip, use_ssl);
}
size_t ProcessReadInput(const char* data, size_t len) {
@@ -2626,10 +2657,10 @@
size_t ProcessWriteInput(const char* data, size_t len) {
char * dataPtr = new char[len];
memcpy(dataPtr, data, len);
- DataFrame df;
- df.data = (const char *)dataPtr;
- df.size = len;
- df.delete_when_done = true;
+ DataFrame* df = new DataFrame;
+ df->data = (const char *)dataPtr;
+ df->size = len;
+ df->delete_when_done = true;
connection_->EnqueueDataFrame(df);
return len;
}
@@ -2684,6 +2715,7 @@
epoll_server_, -1,
acceptor_->https_server_ip_,
acceptor_->https_server_port_,
+ "",
false);
return 1;
@@ -2773,6 +2805,7 @@
vector<SMConnection*> unused_server_connections_;
vector<SMConnection*> tmp_unused_server_connections_;
vector<SMConnection*> allocated_server_connections_;
+ list<SMConnection*> active_server_connections_;
Notification quitting_;
MemoryCache* memory_cache_;
public:
@@ -2806,6 +2839,7 @@
++i) {
delete *i;
}
+ delete ssl_state_;
}
SMConnection* NewConnection() {
@@ -2832,7 +2866,7 @@
epoll_server_.RegisterFD(acceptor_->listen_fd_, this, EPOLLIN | EPOLLET);
}
- void HandleConnection(int server_fd) {
+ void HandleConnection(int server_fd, struct sockaddr_in *remote_addr) {
int on = 1;
int rc;
if (acceptor_->disable_nagle_) {
@@ -2851,12 +2885,15 @@
close(server_fd);
return;
}
+ string remote_ip = inet_ntoa(remote_addr->sin_addr);
server_connection->InitSMConnection(this,
NULL,
&epoll_server_,
server_fd,
- "", "",
+ "", "", remote_ip,
use_ssl_);
+ if (server_connection->initialized())
+ active_server_connections_.push_back(server_connection);
}
void AcceptFromListenFD() {
@@ -2874,7 +2911,7 @@
break;
}
VLOG(1) << ACCEPTOR_CLIENT_IDENT << " Accepted connection";
- HandleConnection(fd);
+ HandleConnection(fd, (struct sockaddr_in *)&address);
}
} else {
while (true) {
@@ -2890,7 +2927,7 @@
break;
}
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Accepted connection";
- HandleConnection(fd);
+ HandleConnection(fd, (struct sockaddr_in *)&address);
}
}
}
@@ -2912,6 +2949,32 @@
quitting_.Notify();
}
+ // Iterates through a list of active connections expiring any that have been
+ // idle longer than the configured timeout.
+ void HandleConnectionIdleTimeout() {
+ int cur_time = time(NULL);
+ static time_t oldest_time = cur_time;
+ // Only iterate the list if we speculate that a connection is ready to be
+ // expired
+ if ((cur_time - oldest_time) < g_proxy_config.idle_timeout_s_)
+ return;
+ list<SMConnection*>::iterator iter = active_server_connections_.begin();
+ while (iter != active_server_connections_.end()) {
+ SMConnection *conn = *iter;
+ int elapsed_time = (cur_time - conn->last_read_time_);
+ if (elapsed_time > g_proxy_config.idle_timeout_s_) {
+ conn->Cleanup("Connection idle timeout reached.");
+ iter = active_server_connections_.erase(iter);
+ continue;
+ }
+ if (conn->last_read_time_ < oldest_time)
+ oldest_time = conn->last_read_time_;
+ iter++;
+ }
+ if ((cur_time - oldest_time) >= g_proxy_config.idle_timeout_s_)
+ oldest_time = cur_time;
+ }
+
void Run() {
while (!quitting_.HasBeenNotified()) {
epoll_server_.set_timeout_in_us(10 * 1000); // 10 ms
@@ -2920,6 +2983,7 @@
tmp_unused_server_connections_.begin(),
tmp_unused_server_connections_.end());
tmp_unused_server_connections_.clear();
+ HandleConnectionIdleTimeout();
}
}
@@ -3000,12 +3064,76 @@
////////////////////////////////////////////////////////////////////////////////
+static bool wantExit = false;
+static bool wantLogClose = false;
+void SignalHandler(int signum)
+{
+ switch(signum) {
+ case SIGTERM:
+ case SIGINT:
+ wantExit = true;
+ break;
+ case SIGHUP:
+ wantLogClose = true;
+ break;
+ }
+}
+
+static int OpenPidFile(const char *pidfile)
+{
+ int fd;
+ struct stat pid_stat;
+ int ret;
+
+ fd = open(pidfile, O_RDWR | O_CREAT, 0600);
+ if (fd == -1) {
+ cerr << "Could not open pid file '" << pidfile << "' for reading.\n";
+ exit(1);
+ }
+
+ ret = flock(fd, LOCK_EX | LOCK_NB);
+ if (ret == -1) {
+ if (errno == EWOULDBLOCK) {
+ cerr << "Flip server is already running.\n";
+ } else {
+ cerr << "Error getting lock on pid file: " << strerror(errno) << "\n";
+ }
+ exit(1);
+ }
+
+ if (fstat(fd, &pid_stat) == -1) {
+ cerr << "Could not stat pid file '" << pidfile << "': " << strerror(errno)
+ << "\n";
+ }
+ if (pid_stat.st_size != 0) {
+ if (ftruncate(fd, pid_stat.st_size) == -1) {
+ cerr << "Could not truncate pid file '" << pidfile << "': "
+ << strerror(errno) << "\n";
+ }
+ }
+
+ char pid_str[8];
+ snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+ int bytes = static_cast<int>(strlen(pid_str));
+ if (write(fd, pid_str, strlen(pid_str)) != bytes) {
+ cerr << "Could not write pid file: " << strerror(errno) << "\n";
+ close(fd);
+ exit(1);
+ }
+
+ return fd;
+}
+
int main (int argc, char**argv)
{
unsigned int i = 0;
bool wait_for_iface = false;
+ int pidfile_fd;
signal(SIGPIPE, SIG_IGN);
+ signal(SIGTERM, SignalHandler);
+ signal(SIGINT, SignalHandler);
+ signal(SIGHUP, SignalHandler);
CommandLine::Init(argc, argv);
CommandLine cl(argc, argv);
@@ -3027,10 +3155,10 @@
<< "\t through the proxy listen ip:port.\n";
cout << "\t--forward-ip-header=<header name>\n";
cout << "\n Server options:\n";
- cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
- << "\t [ssl key filename]\"\n";
- cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],\n"
- << "\t [ssl key filename]\"\n";
+ cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+ << "\n\t [ssl key filename]\"\n";
+ cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+ << "\n\t [ssl key filename]\"\n";
cout << "\t * Leaving the ssl cert and key fields empty will disable ssl"
<< " for the\n"
<< "\t http and spdy flip servers\n";
@@ -3042,10 +3170,18 @@
<< " raised.\n";
cout << "\t--ssl-session-expiry=<seconds> (default is 300)\n";
cout << "\t--ssl-disable-compression\n";
+ cout << "\t--idle-timeout=<seconds> (default is 300)\n";
+ cout << "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n";
cout << "\t--help\n";
exit(0);
}
+ if (cl.HasSwitch("pidfile")) {
+ pidfile_fd = OpenPidFile(cl.GetSwitchValueASCII("pidfile").c_str());
+ } else {
+ pidfile_fd = OpenPidFile(PIDFILE);
+ }
+
g_proxy_config.server_think_time_in_s_ = FLAGS_server_think_time_in_s;
if (cl.HasSwitch("forward-ip-header")) {
@@ -3089,13 +3225,18 @@
if (cl.HasSwitch("ssl-session-expiry")) {
string session_expiry = cl.GetSwitchValueASCII("ssl-session-expiry");
- g_proxy_config.ssl_session_expiry_ = atoi( session_expiry.c_str() );
+ g_proxy_config.ssl_session_expiry_ = atoi(session_expiry.c_str());
}
if (cl.HasSwitch("ssl-disable-compression")) {
g_proxy_config.ssl_disable_compression_ = true;
}
+ if (cl.HasSwitch("idle-timeout")) {
+ g_proxy_config.idle_timeout_s_ =
+ atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
+ }
+
if (cl.HasSwitch("force_spdy"))
FLAGS_force_spdy = true;
@@ -3116,13 +3257,15 @@
LOG(INFO) << "Accepts per wake : " << FLAGS_accepts_per_wake;
LOG(INFO) << "Disable nagle : "
<< (FLAGS_disable_nagle?"true":"false");
- LOG(INFO) << "Reuseport : " << (FLAGS_reuseport?"true":"false");
+ LOG(INFO) << "Reuseport : "
+ << (FLAGS_reuseport?"true":"false");
LOG(INFO) << "Force SPDY : "
<< (FLAGS_force_spdy?"true":"false");
LOG(INFO) << "SSL session expiry : "
<< g_proxy_config.ssl_session_expiry_;
LOG(INFO) << "SSL disable compression : "
<< g_proxy_config.ssl_disable_compression_;
+ LOG(INFO) << "Connection idle timeout : " << g_proxy_config.idle_timeout_s_;
// Proxy Acceptors
while (true) {
@@ -3209,7 +3352,14 @@
sm_worker_threads_.back()->Start();
}
- while (true) {
+ while (!wantExit) {
+ // Close logfile when HUP signal is received. Logging system will
+ // automatically reopen on next log message.
+ if ( wantLogClose ) {
+ wantLogClose = false;
+ VLOG(1) << "HUP received, reopening log file.";
+ logging::CloseLogFile();
+ }
if (GotQuitFromStdin()) {
for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
sm_worker_threads_[i]->Quit();
@@ -3217,10 +3367,12 @@
for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
sm_worker_threads_[i]->Join();
}
- return 0;
+ break;
}
usleep(1000*10); // 10 ms
}
+ unlink(PIDFILE);
+ close(pidfile_fd);
return 0;
}
« no previous file with comments | « net/tools/flip_server/flip_config.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698