testmon: cancelDuringEvent()
This commit is contained in:
1 parent
d5ecc88f3d
commit
a79d65ba15
1 file changed
+35
-1
+35
-1
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user