diff --git a/pdbApp/qsrv.cpp b/pdbApp/qsrv.cpp index 07961db..053524d 100644 --- a/pdbApp/qsrv.cpp +++ b/pdbApp/qsrv.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -12,20 +13,33 @@ namespace pva = epics::pvAccess; -static -epicsMutex qsrv_lock; +namespace { -static -pva::ServerContext::shared_pointer qsrv; +struct qsrv_t { + epicsMutex mutex; + + pva::ServerContext::shared_pointer server; + + pva::ChannelProviderFactory::shared_pointer provider; +} *qsrv; + +} // namespace void qsrvStart() { try{ - epicsGuard G(qsrv_lock); - if(qsrv) { + if(!qsrv) { + qsrv = new qsrv_t; + } + epicsGuard G(qsrv->mutex); + if(qsrv->server) { std::cout<<"QSRV already started\n"; } else { - qsrv = pva::startPVAServer("QSRV", 0, true, false); + qsrv->provider.reset(new BaseChannelProviderFactory("QSRV")); + pva::registerChannelProviderFactory(qsrv->provider); + qsrv->server = pva::startPVAServer("QSRV", 0, true, false); + if(!qsrv->server.unique()) + printf("Warning: new QSRV server instance includes reference loop\n"); } }catch(std::exception& e){ printf("Error: %s\n", e.what()); @@ -35,12 +49,20 @@ void qsrvStart() void qsrvStop() { try{ - epicsGuard G(qsrv_lock); - if(!qsrv) { + epicsGuard G(qsrv->mutex); + if(!qsrv->server) { std::cout<<"QSRV not running\n"; } else { - qsrv->destroy(); - qsrv.reset(); + if(!qsrv->server.unique()) + printf("Warning: QSRV server leaks1\n"); + qsrv->server->destroy(); + if(!qsrv->server.unique()) + printf("Warning: QSRV server leaks2\n"); + qsrv->server.reset(); + pva::unregisterChannelProviderFactory(qsrv->provider); + if(!qsrv->provider.unique()) + printf("Warning: QSRV provider leaks\n"); + qsrv->provider.reset(); } }catch(std::exception& e){ printf("Error: %s\n", e.what()); @@ -51,6 +73,8 @@ static void QSRVExit(void *) { qsrvStop(); + delete qsrv; + qsrv = NULL; } static @@ -65,9 +89,7 @@ void QSRVHooks(initHookState state) static void QSRVRegistrar() { - pva::ChannelProviderFactory::shared_pointer fact(new BaseChannelProviderFactory("QSRV")); initHookRegister(QSRVHooks); - pva::registerChannelProviderFactory(fact); iocshRegister<&qsrvStart>("qsrvStart"); iocshRegister<&qsrvStop>("qsrvStop"); } diff --git a/testApp/Makefile b/testApp/Makefile index 899b9fb..dda60f2 100644 --- a/testApp/Makefile +++ b/testApp/Makefile @@ -11,7 +11,8 @@ USR_CPPFLAGS += -I$(TOP)/common TARGETS += $(COMMON_DIR)/p2pTestIoc.dbd p2pTestIoc_DBD += base.dbd -p2pTestIoc_DBD += qsrv.dbd +# Tests explicitly create/destory PDB provider +#p2pTestIoc_DBD += qsrv.dbd LIBRARY += testutils diff --git a/testApp/testpvif.cpp b/testApp/testpvif.cpp index 1ada640..7477c66 100644 --- a/testApp/testpvif.cpp +++ b/testApp/testpvif.cpp @@ -15,6 +15,8 @@ namespace pvd = epics::pvData; extern "C" void p2pTestIoc_registerRecordDeviceDriver(struct dbBase *); +void qsrvStop(); + namespace { void testScalar() @@ -198,6 +200,8 @@ void testScalar() pvif_mbbi->get(mask); testEqual(prec_mbbi->val, 2); dbScanUnlock((dbCommon*)prec_mbbi); + + qsrvStop(); } } // namespace