Skip to content

Commit 96a5cbb

Browse files
committed
rgw_lc: replace strftime w/fmt and chrono:calendar
It's reliably claimed that std::strftime is not mt-safe, and this would be a likely root cause of intermittent scrambled expiration header output cases that have been reported. Fixes: https://tracker.ceph.com/issues/63973 Signed-off-by: Matt Benjamin <[email protected]>
1 parent 98242a7 commit 96a5cbb

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

src/rgw/rgw_lc.cc

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
22
// vim: ts=8 sw=2 smarttab ft=cpp
33

4+
#include <fmt/chrono.h>
45
#include <string.h>
56
#include <iostream>
67
#include <map>
@@ -2816,18 +2817,11 @@ std::string s3_expiration_header(
28162817

28172818
// cond format header
28182819
if (expiration_date && rule_id) {
2819-
// Fri, 23 Dec 2012 00:00:00 GMT
2820-
char exp_buf[100];
2821-
time_t exp = ceph::real_clock::to_time_t(*expiration_date);
2822-
if (std::strftime(exp_buf, sizeof(exp_buf),
2823-
"%a, %d %b %Y %T %Z", std::gmtime(&exp))) {
2824-
hdr = fmt::format("expiry-date=\"{0}\", rule-id=\"{1}\"", exp_buf,
2825-
*rule_id);
2826-
} else {
2827-
ldpp_dout(dpp, 0) << __func__ <<
2828-
"() strftime of life cycle expiration header failed"
2829-
<< dendl;
2830-
}
2820+
auto exp = ceph::real_clock::to_time_t(*expiration_date);
2821+
// Fri, 21 Dec 2012 00:00:00 GMT
2822+
auto exp_str = fmt::format("{:%a, %d %b %Y %T %Z}", fmt::gmtime(exp));
2823+
hdr = fmt::format("expiry-date=\"{0}\", rule-id=\"{1}\"", exp_str,
2824+
*rule_id);
28312825
}
28322826

28332827
return hdr;

src/test/rgw/test_rgw_lc.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <gtest/gtest.h>
88
#include <string>
99
#include <vector>
10+
#include <chrono>
1011
#include <stdexcept>
1112

1213
static const char* xmldoc_1 =
@@ -107,6 +108,17 @@ TEST(TestLCFilterInvalidAnd, XMLDoc3)
107108
ASSERT_EQ(filter.get_flags(), uint32_t(LCFlagType::none));
108109
}
109110

111+
TEST(ExpHdr, ReplaceStrftime)
112+
{
113+
using namespace std::chrono;
114+
115+
constexpr auto dec21 = year(2012)/12/21;
116+
auto exp = sys_days(dec21) + 9h + 13min + 7s ;
117+
auto exp_str = fmt::format("{:%a, %d %b %Y %T %Z}", fmt::gmtime(exp));
118+
std::cout << "exp_str: " << exp_str << std::endl;
119+
ASSERT_EQ(exp_str, "Fri, 21 Dec 2012 09:13:07 GMT");
120+
}
121+
110122
struct LCWorkTimeTests : ::testing::Test
111123
{
112124
CephContext* cct;

0 commit comments

Comments
 (0)