Skip to content

Commit a16d072

Browse files
committed
MB-45599: Use stack buffer in SendResponse
ep-engine copies the response handler and calls it from a background thread in some cases and it'll end up racing on the thread local scratch buffer we used to format the package header into. To work around this problem use a stack allocated buffer as the buffer is only 27 bytes big (24 for the header, 3 for frame info) Change-Id: I405409e4fc4c565fc9eca3ae2d0355d1ff3103c7 Reviewed-on: http://review.couchbase.org/c/kv_engine/+/151030 Tested-by: Build Bot <[email protected]> Reviewed-by: Daniel Owen <[email protected]>
1 parent fe096c2 commit a16d072

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

daemon/connection.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,14 +1598,20 @@ void Connection::setDcpFlowControlBufferSize(std::size_t size) {
15981598
}
15991599

16001600
std::string_view Connection::formatResponseHeaders(Cookie& cookie,
1601-
std::array<char, 2048>& dest,
1601+
cb::char_buffer dest,
16021602
cb::mcbp::Status status,
16031603
std::size_t extras_len,
16041604
std::size_t key_len,
16051605
std::size_t value_len,
16061606
uint8_t datatype) {
1607+
if (dest.size() < sizeof(cb::mcbp::Response) + MCBP_TRACING_RESPONSE_SIZE) {
1608+
throw std::runtime_error(
1609+
"Connection::formatResponseHeaders: The provided buffer must "
1610+
"be big enough to hold header and tracing frame info");
1611+
}
1612+
16071613
const auto& request = cookie.getRequest();
1608-
auto wbuf = cb::char_buffer{dest.data(), dest.size()};
1614+
auto wbuf = dest;
16091615
auto& response = *reinterpret_cast<cb::mcbp::Response*>(wbuf.data());
16101616

16111617
response.setOpcode(request.getClientOpcode());
@@ -1677,8 +1683,11 @@ void Connection::sendResponseHeaders(Cookie& cookie,
16771683
std::string_view key,
16781684
std::size_t value_len,
16791685
uint8_t datatype) {
1686+
std::array<char, sizeof(cb::mcbp::Response) + MCBP_TRACING_RESPONSE_SIZE>
1687+
buffer;
1688+
16801689
auto wbuf = formatResponseHeaders(cookie,
1681-
thread.scratch_buffer,
1690+
{buffer.data(), buffer.size()},
16821691
status,
16831692
extras.size(),
16841693
key.size(),
@@ -1704,8 +1713,11 @@ void Connection::sendResponse(Cookie& cookie,
17041713
cookie, status, extras, key, value.size(), datatype);
17051714
chainDataToOutputStream(std::move(sendbuffer));
17061715
} else {
1716+
std::array<char,
1717+
sizeof(cb::mcbp::Response) + MCBP_TRACING_RESPONSE_SIZE>
1718+
buffer;
17071719
auto wbuf = formatResponseHeaders(cookie,
1708-
thread.scratch_buffer,
1720+
{buffer.data(), buffer.size()},
17091721
status,
17101722
extras.size(),
17111723
key.size(),

daemon/connection.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -868,13 +868,7 @@ class Connection : public DcpMessageProducersIface {
868868
* Format the response header into the provided buffer.
869869
*
870870
* @param cookie The command to create a response for
871-
* @param dest The destination buffer (the reason the buffer is huge
872-
* is that we'll be using the front-end-threads scratch
873-
* buffer and I don't want to do runtime checks to verify
874-
* that it is big enough when we can use a compile time
875-
* check (if someone change the size of the front-end-threads
876-
* scratch buffer we'll fail compile time when we pass it
877-
* in here)
871+
* @param dest The destination buffer
878872
* @param status The status code
879873
* @param extras_len The length of the extras section
880874
* @param key_len The length of the key
@@ -883,7 +877,7 @@ class Connection : public DcpMessageProducersIface {
883877
* @return A view into the destination buffer containing the header
884878
*/
885879
std::string_view formatResponseHeaders(Cookie& cookie,
886-
std::array<char, 2048>& dest,
880+
cb::char_buffer dest,
887881
cb::mcbp::Status status,
888882
std::size_t extras_len,
889883
std::size_t key_len,

0 commit comments

Comments
 (0)