From 22e93e8e0de1e35237035c456a30c5b387c7ed12 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Thu, 11 Aug 2011 13:16:34 +0200 Subject: [PATCH] UDP shutdown on linux --- pvAccessApp/remote/blockingUDP.h | 2 ++ pvAccessApp/remote/blockingUDPTransport.cpp | 36 +++++++++++++++++++++ testApp/Makefile | 2 +- testApp/client/Makefile | 18 +++++++---- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/pvAccessApp/remote/blockingUDP.h b/pvAccessApp/remote/blockingUDP.h index 26da36a..ddcf571 100644 --- a/pvAccessApp/remote/blockingUDP.h +++ b/pvAccessApp/remote/blockingUDP.h @@ -210,6 +210,8 @@ namespace epics { std::auto_ptr _responseHandler; virtual void processRead(); + + void wakeupMessage(); private: static void threadRunner(void* param); diff --git a/pvAccessApp/remote/blockingUDPTransport.cpp b/pvAccessApp/remote/blockingUDPTransport.cpp index f896ae0..c5f2df9 100644 --- a/pvAccessApp/remote/blockingUDPTransport.cpp +++ b/pvAccessApp/remote/blockingUDPTransport.cpp @@ -52,6 +52,24 @@ namespace epics { _threadId(0) { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(blockingUDPTransport); + + /* + osiSockAddr tmpAddr; + osiSocklen_t saddr_length = sizeof (tmpAddr); + int status = ::getsockname(_channel, &tmpAddr.sa, &saddr_length); + if (status < 0) + { + char strBuffer[64]; + epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer)); + errlogSevPrintf(errlogMinor, "getsockname error: %s", strBuffer); + } + else + { + int localPort = ntohs(tmpAddr.ia.sin_port); + } + */ + //errlogSevPrintf(errlogInfo, "UDP bind adrr port: %d", ntohs(_bindAddress.ia.sin_port)); + } BlockingUDPTransport::~BlockingUDPTransport() { @@ -87,6 +105,9 @@ namespace epics { if(_closed) return; _closed = true; + // to get out of blocking receive + wakeupMessage(); + errlogSevPrintf(errlogInfo, "UDP socket %s closed.", inetAddressToString(_bindAddress).c_str()); @@ -94,6 +115,7 @@ namespace epics { epicsSocketDestroy(_channel); } + // wait for send thread to exit cleanly if (waitForThreadToComplete) _shutdownEvent.wait(); @@ -264,6 +286,20 @@ namespace epics { return true; } + + + void BlockingUDPTransport::wakeupMessage() + { + osiSockAddr addr; + addr.ia.sin_family = AF_INET; + addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.ia.sin_port = _bindAddress.ia.sin_port; + + // send a wakeup msg so the UDP recv thread will exit + sendto(_channel, static_cast(0), + 0, 0, &addr.sa, sizeof(addr.sa )); + } + bool BlockingUDPTransport::send(ByteBuffer* buffer) { if(!_sendAddresses) return false; diff --git a/testApp/Makefile b/testApp/Makefile index eebf51c..0b70107 100644 --- a/testApp/Makefile +++ b/testApp/Makefile @@ -1,6 +1,6 @@ TOP = .. include $(TOP)/configure/CONFIG DIRS += utils -#DIRS += client +DIRS += client DIRS += remote include $(TOP)/configure/RULES_DIRS diff --git a/testApp/client/Makefile b/testApp/client/Makefile index 2eee695..64e752b 100644 --- a/testApp/client/Makefile +++ b/testApp/client/Makefile @@ -2,18 +2,22 @@ TOP=../.. include $(TOP)/configure/CONFIG -PROD_HOST += testChannelAccessFactory -testChannelAccessFactory_SRCS += testChannelAccessFactory.cpp -testChannelAccessFactory_LIBS += pvData pvAccess Com +#PROD_HOST += testChannelAccessFactory +testChannelAccessFactory_SRCS = testChannelAccessFactory.cpp +testChannelAccessFactory_LIBS = pvData pvAccess Com -PROD_HOST += testCreateRequest -testCreateRequest_SRCS += testCreateRequest.cpp -testCreateRequest_LIBS += pvData pvAccess Com +#PROD_HOST += testCreateRequest +testCreateRequest_SRCS = testCreateRequest.cpp +testCreateRequest_LIBS = pvData pvAccess Com -PROD_HOST += testMockClient +#PROD_HOST += testMockClient testMockClient_SRCS = testMockClient.cpp MockClientImpl.cpp testMockClient_LIBS = pvData pvAccess Com +PROD_HOST += testStartStop +testStartStop_SRCS = testStartStop.cpp +testStartStop_LIBS = pvData pvAccess Com + include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE