fix pvalink shutdown during tests
This commit is contained in:
@ -85,3 +85,4 @@ include $(TOP)/configure/RULES
|
||||
$(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@
|
||||
|
||||
qsrv$(DEP): ../O.Common/pv/qsrvVersionNum.h
|
||||
pvalink$(DEP): ../O.Common/pv/qsrvVersionNum.h
|
||||
|
@ -25,6 +25,34 @@ epicsShareExtern unsigned qsrvVersion(void);
|
||||
/** returns QSRV_ABI_VERSION_INT captured at compilation time */
|
||||
epicsShareExtern unsigned qsrvABIVersion(void);
|
||||
|
||||
/** Call before testIocShutdownOk()
|
||||
@code
|
||||
testdbPrepare();
|
||||
...
|
||||
testIocInitOk();
|
||||
...
|
||||
testqsrvShutdownOk();
|
||||
testIocShutdownOk();
|
||||
testqsrvCleanup();
|
||||
testdbCleanup();
|
||||
@endcode
|
||||
*/
|
||||
epicsShareExtern void testqsrvShutdownOk(void);
|
||||
|
||||
/** Call after testIocShutdownOk() and before testdbCleanup()
|
||||
@code
|
||||
testdbPrepare();
|
||||
...
|
||||
testIocInitOk();
|
||||
...
|
||||
testqsrvShutdownOk();
|
||||
testIocShutdownOk();
|
||||
testqsrvCleanup();
|
||||
testdbCleanup();
|
||||
@endcode
|
||||
*/
|
||||
epicsShareExtern void testqsrvCleanup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <epicsAtomic.h>
|
||||
#include <link.h>
|
||||
#include <dbJLink.h>
|
||||
#include <epicsUnitTest.h>
|
||||
|
||||
#include <epicsStdio.h> /* redirects stdout/stderr */
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
@ -26,6 +28,7 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include <shareLib.h>
|
||||
|
||||
#include "pv/qsrv.h"
|
||||
#include "helper.h"
|
||||
#include "pvif.h"
|
||||
#include "pvalink.h"
|
||||
@ -39,30 +42,53 @@ using namespace pvalink;
|
||||
|
||||
namespace {
|
||||
|
||||
// halt, and clear, scan workers before dbCloseLinks() (cf. iocShutdown())
|
||||
static void shutdownStep1()
|
||||
{
|
||||
// no locking here as we assume that shutdown doesn't race startup
|
||||
if(!pvaGlobal) return;
|
||||
|
||||
pvaGlobal->queue.close();
|
||||
}
|
||||
|
||||
// Cleanup pvaGlobal, including PVA client and QSRV providers ahead of PDB cleanup
|
||||
// specifically QSRV provider must be free'd prior to db_cleanup_events()
|
||||
static void shutdownStep2()
|
||||
{
|
||||
if(!pvaGlobal) return;
|
||||
|
||||
{
|
||||
Guard G(pvaGlobal->lock);
|
||||
if(pvaGlobal->channels.size()) {
|
||||
fprintf(stderr, "pvaLink leaves %zu channels open\n",
|
||||
pvaGlobal->channels.size());
|
||||
}
|
||||
}
|
||||
|
||||
delete pvaGlobal;
|
||||
pvaGlobal = NULL;
|
||||
}
|
||||
|
||||
static void stopPVAPool(void*)
|
||||
{
|
||||
pvaGlobal->queue.close();
|
||||
try {
|
||||
shutdownStep1();
|
||||
}catch(std::exception& e){
|
||||
fprintf(stderr, "Error while stopping PVA link pool : %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
static void finalizePVA(void*)
|
||||
{
|
||||
try {
|
||||
{
|
||||
Guard G(pvaGlobal->lock);
|
||||
if(pvaGlobal->channels.size()) {
|
||||
fprintf(stderr, "pvaLink leaves %zu channels open\n",
|
||||
pvaGlobal->channels.size());
|
||||
}
|
||||
}
|
||||
|
||||
delete pvaGlobal;
|
||||
pvaGlobal = NULL;
|
||||
|
||||
shutdownStep2();
|
||||
}catch(std::exception& e){
|
||||
fprintf(stderr, "Error initializing pva link handling : %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool atexitInstalled;
|
||||
|
||||
void initPVALink(initHookState state)
|
||||
{
|
||||
if(state==initHookAfterCaLinkInit) {
|
||||
@ -70,9 +96,15 @@ void initPVALink(initHookState state)
|
||||
// so hook registered here will be run after iocShutdown()
|
||||
// which closes links
|
||||
try {
|
||||
if(pvaGlobal) {
|
||||
cantProceed("# Missing call to testqsrvShutdownOk() and/or testqsrvCleanup()");
|
||||
}
|
||||
pvaGlobal = new pvaGlobal_t;
|
||||
|
||||
epicsAtExit(finalizePVA, NULL);
|
||||
if(!atexitInstalled) {
|
||||
epicsAtExit(finalizePVA, NULL);
|
||||
atexitInstalled = true;
|
||||
}
|
||||
|
||||
}catch(std::exception& e){
|
||||
cantProceed("Error initializing pva link handling : %s\n", e.what());
|
||||
@ -87,6 +119,25 @@ void initPVALink(initHookState state)
|
||||
|
||||
} // namespace
|
||||
|
||||
// halt, and clear, scan workers before dbCloseLinks() (cf. iocShutdown())
|
||||
void testqsrvShutdownOk(void)
|
||||
{
|
||||
try {
|
||||
shutdownStep1();
|
||||
}catch(std::exception& e){
|
||||
testAbort("Error while stopping PVA link pool : %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void testqsrvCleanup(void)
|
||||
{
|
||||
try {
|
||||
shutdownStep2();
|
||||
}catch(std::exception& e){
|
||||
testAbort("Error initializing pva link handling : %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void installPVAAddLinkHook()
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <dbUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/qsrv.h>
|
||||
#include "utilities.h"
|
||||
#include "pvalink.h"
|
||||
|
||||
@ -70,7 +71,9 @@ MAIN(testpvalink)
|
||||
IOC.init();
|
||||
testGet();
|
||||
testPut();
|
||||
testqsrvShutdownOk();
|
||||
IOC.shutdown();
|
||||
testqsrvCleanup();
|
||||
|
||||
}catch(std::exception& e){
|
||||
testFail("Unexpected exception: %s", e.what());
|
||||
|
Reference in New Issue
Block a user