Skip to content

Commit 562aa72

Browse files
committed
MB-68823: Merge trinity/9a76d5e99 into morpheus
* 9a76d5e MB-68823: Revert log to pre review.couchbase.org/c/kv_engine/+/234445 * 6d16ff8 MB-68823: Don't throw EPEngine exception to core in StreamReq path Change-Id: I994d7defc72791a24d0c5f98f74b865dcda16dea
2 parents 1815f7b + 9a76d5e commit 562aa72

File tree

5 files changed

+95
-3
lines changed

5 files changed

+95
-3
lines changed

daemon/protocol/mcbp/engine_wrapper.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,9 +845,11 @@ cb::engine_errc dcpStreamReq(Cookie& cookie,
845845
std::move(callback),
846846
json);
847847
if (ret == cb::engine_errc::disconnect) {
848-
LOG_WARNING_CTX("dcp.stream_req returned cb::engine_errc::disconnect",
849-
{"conn_id", connection.getId()},
850-
{"description", connection.getDescription()});
848+
LOG_WARNING(
849+
"{}: dcp.stream_req returned cb::engine_errc::disconnect - "
850+
"Cookie {}",
851+
connection.getId(),
852+
cookie.to_json().dump());
851853
connection.setTerminationReason("Engine forced disconnect");
852854
}
853855
return ret;

engines/ep/src/ep_engine.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,10 @@ cb::engine_errc EventuallyPersistentEngine::stream_req(
14241424
{"error", e.what()},
14251425
{"status", e.engine_code()});
14261426
return cb::engine_errc(e.code().value());
1427+
} catch (const std::exception& e) {
1428+
EP_LOG_ERR("EventuallyPersistentEngine::stream_req: Exception {}",
1429+
e.what());
1430+
return cb::engine_errc::disconnect;
14271431
}
14281432
}
14291433

tests/testapp/testapp_bucket.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,72 @@ TEST_P(BucketTest, DeleteSelectedBucket) {
359359
adminConnection->selectBucket("bucket");
360360
deleteBucket(*adminConnection, "bucket", [](const std::string&) {});
361361
}
362+
363+
class MemTrackingBucketTest : public BucketTest {
364+
public:
365+
static void SetUpTestCase() {
366+
// Note: Important to set the env BEFORE starting memcached,
367+
// env vars wouldn't be passed to the memcached process otherwise
368+
// (unless testapp is run in -e (embedded) mode)
369+
ASSERT_FALSE(getenv("CB_ARENA_MALLOC_VERIFY_DEALLOC_CLIENT"));
370+
ASSERT_EQ(0, setenv("CB_ARENA_MALLOC_VERIFY_DEALLOC_CLIENT", "1", 0));
371+
BucketTest::SetUpTestCase();
372+
}
373+
374+
static void TearDownTestCase() {
375+
EXPECT_EQ(0, unsetenv("CB_ARENA_MALLOC_VERIFY_DEALLOC_CLIENT"));
376+
BucketTest::TearDownTestCase();
377+
}
378+
};
379+
380+
INSTANTIATE_TEST_SUITE_P(TransportProtocols,
381+
MemTrackingBucketTest,
382+
::testing::Values(TransportProtocols::McbpSsl),
383+
::testing::PrintToStringParamName());
384+
385+
TEST_P(MemTrackingBucketTest, MB_68823) {
386+
// Note: Not using adminConnection as the connection in the test is
387+
// forcibly disconnected and we need adminConnection at TearDown.
388+
auto& conn = getConnection();
389+
conn.authenticate("@admin");
390+
conn.selectBucket(bucketName);
391+
conn.setFeature(cb::mcbp::Feature::JSON, true);
392+
conn.setFeature(cb::mcbp::Feature::Collections, true);
393+
conn.dcpOpenProducer("dcp-conn_invalid-stream-req-filter");
394+
conn.dcpControl("enable_noop", "true");
395+
396+
// Invalid StreamReq filter (with cid duplicate) throws in Filter::ctor.
397+
// Before the fix the test fails by:
398+
//
399+
// ===ERROR===: JeArenaMalloc deallocation mismatch
400+
// Memory freed by client:100 domain:None which is assigned arena:0,
401+
// but memory was previously allocated from arena:2 (client-specific
402+
// arena).
403+
// Allocation address:0x10b1b1080 size:192
404+
try {
405+
conn.dcpStreamRequest(Vbid(0),
406+
cb::mcbp::DcpAddStreamFlag::None,
407+
0, // startSeq
408+
~0, // endSeq,
409+
0, // vbUuid
410+
0, // snapStart
411+
0, // snapEnd
412+
R"({"collections":["0", "0"]})"_json); // filter
413+
} catch (const std::exception&) {
414+
const auto timeout =
415+
std::chrono::steady_clock::now() + std::chrono::seconds{10};
416+
const auto line =
417+
"EventuallyPersistentEngine::stream_req: Exception GSL: "
418+
"Precondition failure: 'emplaced'";
419+
const auto expectedLogInstances = 1;
420+
do {
421+
if (mcd_env->verifyLogLine(line) == expectedLogInstances) {
422+
return;
423+
}
424+
std::this_thread::sleep_for(std::chrono::milliseconds{100});
425+
} while (std::chrono::steady_clock::now() < timeout);
426+
427+
FAIL() << "Timeout before the log line was dumped to the file";
428+
}
429+
FAIL() << "StreamRequest should have failed";
430+
}

tests/testapp/testapp_environment.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,17 @@ bool McdEnvironment::iterateAuditEvents(
421421
return false;
422422
}
423423

424+
size_t McdEnvironment::verifyLogLine(std::string_view string) const {
425+
size_t ret = 0;
426+
mcd_env->iterateLogLines([&string, &ret](auto line) {
427+
if (line.find(string) != std::string_view::npos) {
428+
++ret;
429+
}
430+
return true;
431+
});
432+
return ret;
433+
}
434+
424435
std::string McdEnvironment::readConcurrentUpdatedFile(
425436
const cb::dek::Entity entity, const std::filesystem::path& path) const {
426437
std::string content;

tests/testapp/testapp_environment.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ class McdEnvironment {
275275
bool iterateAuditEvents(
276276
const std::function<bool(const nlohmann::json&)>& callback) const;
277277

278+
/**
279+
* @param string to search
280+
* @return The number of instances of string in the memcached log file
281+
*/
282+
size_t verifyLogLine(std::string_view string) const;
283+
278284
/// Do we have support for IPv4 addresses on the machine
279285
[[nodiscard]] bool haveIPv4() const {
280286
return !ipaddresses.first.empty();

0 commit comments

Comments
 (0)