nghttpd: Fix data race when updating cached_date

This commit is contained in:
Tatsuhiro Tsujikawa 2015-01-08 21:41:26 +09:00
parent 5473e870eb
commit f570757701
1 changed files with 32 additions and 23 deletions

View File

@ -163,16 +163,6 @@ void remove_stream_write_timeout(Stream *stream) {
} }
} // namespace } // namespace
namespace {
std::shared_ptr<std::string> cached_date;
} // namespace
namespace {
void refresh_cb(struct ev_loop *loop, ev_timer *w, int revents) {
cached_date = std::make_shared<std::string>(util::http_date(time(nullptr)));
}
} // namespace
namespace { namespace {
void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config); void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config);
} // namespace } // namespace
@ -242,9 +232,12 @@ public:
} }
add_handler(handler.release()); add_handler(handler.release());
} }
void update_cached_date() { cached_date_ = util::http_date(time(nullptr)); }
const std::string &get_cached_date() const { return cached_date_; }
private: private:
std::set<Http2Handler *> handlers_; std::set<Http2Handler *> handlers_;
std::string cached_date_;
struct ev_loop *loop_; struct ev_loop *loop_;
const Config *config_; const Config *config_;
SSL_CTX *ssl_ctx_; SSL_CTX *ssl_ctx_;
@ -673,7 +666,6 @@ int Http2Handler::submit_file_response(const std::string &status,
Stream *stream, time_t last_modified, Stream *stream, time_t last_modified,
off_t file_length, off_t file_length,
nghttp2_data_provider *data_prd) { nghttp2_data_provider *data_prd) {
auto date_str = cached_date;
std::string content_length = util::utos(file_length); std::string content_length = util::utos(file_length);
std::string last_modified_str; std::string last_modified_str;
nghttp2_nv nva[] = { nghttp2_nv nva[] = {
@ -681,7 +673,7 @@ int Http2Handler::submit_file_response(const std::string &status,
http2::make_nv_ls("server", NGHTTPD_SERVER), http2::make_nv_ls("server", NGHTTPD_SERVER),
http2::make_nv_ls("content-length", content_length), http2::make_nv_ls("content-length", content_length),
http2::make_nv_ll("cache-control", "max-age=3600"), http2::make_nv_ll("cache-control", "max-age=3600"),
http2::make_nv_ls("date", *date_str), http2::make_nv_ls("date", sessions_->get_cached_date()),
http2::make_nv_ll("", ""), http2::make_nv_ll("", ""),
}; };
size_t nvlen = 5; size_t nvlen = 5;
@ -696,11 +688,10 @@ int Http2Handler::submit_file_response(const std::string &status,
int Http2Handler::submit_response(const std::string &status, int32_t stream_id, int Http2Handler::submit_response(const std::string &status, int32_t stream_id,
const Headers &headers, const Headers &headers,
nghttp2_data_provider *data_prd) { nghttp2_data_provider *data_prd) {
auto date_str = cached_date; auto nva = std::vector<nghttp2_nv>{
auto nva = http2::make_nv_ls(":status", status),
std::vector<nghttp2_nv>{http2::make_nv_ls(":status", status), http2::make_nv_ls("server", NGHTTPD_SERVER),
http2::make_nv_ls("server", NGHTTPD_SERVER), http2::make_nv_ls("date", sessions_->get_cached_date())};
http2::make_nv_ls("date", *date_str)};
for (auto &nv : headers) { for (auto &nv : headers) {
nva.push_back(http2::make_nv(nv.name, nv.value, nv.no_index)); nva.push_back(http2::make_nv(nv.name, nv.value, nv.no_index));
} }
@ -1311,7 +1302,23 @@ void worker_acceptcb(struct ev_loop *loop, ev_async *w, int revents) {
} // namespace } // namespace
namespace { namespace {
void run_worker(Worker *worker) { ev_run(worker->sessions->get_loop(), 0); } void refresh_cb(struct ev_loop *loop, ev_timer *w, int revents) {
auto sessions = static_cast<Sessions *>(w->data);
sessions->update_cached_date();
}
} // namespace
namespace {
void run_worker(Worker *worker) {
auto loop = worker->sessions->get_loop();
ev_timer w;
ev_timer_init(&w, refresh_cb, 0., 1.);
w.data = worker->sessions.get();
ev_timer_again(loop, &w);
worker->sessions->update_cached_date();
ev_run(loop, 0);
}
} // namespace } // namespace
class AcceptHandler { class AcceptHandler {
@ -1637,11 +1644,13 @@ int HttpServer::run() {
return -1; return -1;
} }
ev_timer refresh_wtc; ev_timer refresh_timer;
ev_timer_init(&refresh_wtc, refresh_cb, 1.0, 0.); ev_timer_init(&refresh_timer, refresh_cb, 0., 1.);
ev_timer_again(loop, &refresh_wtc); refresh_timer.data = &sessions;
if (config_->num_worker == 1) {
cached_date = std::make_shared<std::string>(util::http_date(time(nullptr))); ev_timer_again(loop, &refresh_timer);
sessions.update_cached_date();
}
ev_run(loop, 0); ev_run(loop, 0);
return 0; return 0;