testmon: cancelDuringEvent()

This commit is contained in:
George McIntyre authored and Michael Davidsaver committed 2026-07-09 11:54:00 -07:00
1 parent d5ecc88f3d
commit a79d65ba15
1 file changed
+35 -1
+35 -1
View File
@@ -128,6 +128,39 @@ struct BasicTest {
testOk1(!done->wait(1.1));
}
void cancelDuringEvent()
{
testShow()<<__func__;
mbox.open(initial);
serv.start();
// A heap-allocated captured value the callback reads AFTER cancelling.
// If the functor (and this capture) were freed by the in-call cancel,
// touching `canary` would be a use-after-free (caught under ASan).
auto canary(std::make_shared<std::string>("alive"));
auto fired(std::make_shared<epicsEvent>());
auto ok(std::make_shared<std::atomic<bool>>(false));
std::shared_ptr<client::Subscription> self;
self = cli.monitor("mailbox")
.maskConnected(true)
.maskDisconnected(true)
.event([canary, fired, ok](client::Subscription& s) {
// Re-entrant cancel on this same loop: move-destroys `event`.
s.cancel();
// Touch the capture after the cancel; must still be valid.
ok->store(*canary == "alive");
fired->signal();
})
.exec();
post(1);
testOk1(fired->wait(5.0));
testOk1(ok->load());
}
void badRequest()
{
testShow()<<__func__;
@@ -381,13 +414,14 @@ struct TestReconn : public BasicTest
MAIN(testmon)
{
testPlan(43);
testPlan(45);
testSetup();
try{
logger_config_env();
BasicTest().orphan();
BasicTest().cancel();
BasicTest().asyncCancel();
BasicTest().cancelDuringEvent();
BasicTest().badRequest();
BasicTest().testNoMark();
TestLifeCycle().testBasic(true);