From 7653151cb08cfa40eec22e7aac3068b009207bc8 Mon Sep 17 00:00:00 2001 From: Henri Herscher Date: Tue, 15 Nov 2005 04:19:31 +0000 Subject: Improvements in the shutdown procedure (NT service does not crash on exit anymore, give two seconds to threads to exit properly). git-svn-id: https://oreka.svn.sourceforge.net/svnroot/oreka/trunk@44 09dcff7a-b715-0410-9601-b79a96267cd0 --- orkaudio/AudioCapturePlugin.h | 3 +- orkaudio/BatchProcessing.cpp | 81 +++++++++++++--------- orkaudio/CapturePluginProxy.cpp | 24 ++++++- orkaudio/CapturePluginProxy.h | 1 + orkaudio/Daemon.cpp | 8 +++ orkaudio/Daemon.h | 3 + orkaudio/ImmediateProcessing.cpp | 29 ++++++-- orkaudio/LogManager.cpp | 8 ++- orkaudio/LogManager.h | 7 +- orkaudio/OrkAudio.cpp | 29 +++++++- orkaudio/Reporting.cpp | 56 ++++++++++----- orkaudio/ThreadSafeQueue.h | 12 ++-- .../common/AudioCapturePluginCommon.cpp | 4 +- .../common/AudioCapturePluginCommon.h | 3 +- .../audiocaptureplugins/generator/Generator.cpp | 2 +- .../sounddevice/SoundDevice.cpp | 2 +- orkaudio/audiocaptureplugins/voip/VoIp.cpp | 14 +++- 17 files changed, 208 insertions(+), 78 deletions(-) diff --git a/orkaudio/AudioCapturePlugin.h b/orkaudio/AudioCapturePlugin.h index b3469ec..d2bd2e7 100644 --- a/orkaudio/AudioCapturePlugin.h +++ b/orkaudio/AudioCapturePlugin.h @@ -34,9 +34,10 @@ typedef void (__CDECL__*CaptureEventCallBackFunction)(CaptureEventRef, CStdStrin // Exported functions definitions -typedef void (__CDECL__* RegisterCallBacksFunction)(AudioChunkCallBackFunction, CaptureEventCallBackFunction, LogManager*); +typedef void (__CDECL__* RegisterCallBacksFunction)(AudioChunkCallBackFunction, CaptureEventCallBackFunction, OrkLogManager*); typedef void (__CDECL__* InitializeFunction)(); typedef void (__CDECL__* RunFunction)(); +typedef void (__CDECL__* ShutdownFunction)(); typedef void (__CDECL__* ConfigureFunction)(DOMNode*); typedef void (__CDECL__* StartCaptureFunction)(CStdString& port); typedef void (__CDECL__* StopCaptureFunction)(CStdString& port); diff --git a/orkaudio/BatchProcessing.cpp b/orkaudio/BatchProcessing.cpp index e154cb7..130161c 100644 --- a/orkaudio/BatchProcessing.cpp +++ b/orkaudio/BatchProcessing.cpp @@ -16,6 +16,7 @@ #include "LogManager.h" #include "ace/OS_NS_unistd.h" #include "audiofile/LibSndFileFile.h" +#include "Daemon.h" BatchProcessing BatchProcessing::m_batchProcessingSingleton; @@ -50,47 +51,59 @@ void BatchProcessing::ThreadHandler(void *args) CStdString threadIdString = IntToString(threadId); LOG4CXX_DEBUG(LOG.batchProcessingLog, CStdString("Created thread #") + threadIdString); - for(;;) + bool stop = false; + + for(;stop == false;) { try { AudioTapeRef audioTapeRef = pBatchProcessing->m_audioTapeQueue.pop(); - CStdString threadIdString = IntToString(threadId); - LOG4CXX_INFO(LOG.batchProcessingLog, CStdString("Th") + threadIdString + " processing: " + audioTapeRef->GetIdentifier()); - - AudioFileRef fileRef = audioTapeRef->GetAudioFileRef(); - fileRef->MoveOrig(); - fileRef->Open(AudioFile::READ); - - AudioChunkRef chunkRef; - AudioFileRef outFileRef; - - switch(CONFIG.m_storageAudioFormat) + if(audioTapeRef.get() == NULL) { - case AudioTape::FfUlaw: - outFileRef.reset(new LibSndFileFile(SF_FORMAT_ULAW | SF_FORMAT_WAV)); - break; - case AudioTape::FfAlaw: - outFileRef.reset(new LibSndFileFile(SF_FORMAT_ALAW | SF_FORMAT_WAV)); - break; - case AudioTape::FfGsm: - default: - outFileRef.reset(new LibSndFileFile(SF_FORMAT_GSM610 | SF_FORMAT_WAV)); + if(DaemonSingleton::instance()->IsStopping()) + { + stop = true; + } } - CStdString file = CONFIG.m_audioOutputPath + "/" + audioTapeRef->GetPath() + audioTapeRef->GetIdentifier(); - outFileRef->Open(file, AudioFile::WRITE); - - while(fileRef->ReadChunkMono(chunkRef)) + else { - outFileRef->WriteChunk(chunkRef); - } - - if(CONFIG.m_deleteNativeFile) - { - fileRef->Close(); - fileRef->Delete(); CStdString threadIdString = IntToString(threadId); - LOG4CXX_INFO(LOG.batchProcessingLog, CStdString("Th") + threadIdString + " deleting native: " + audioTapeRef->GetIdentifier()); + LOG4CXX_INFO(LOG.batchProcessingLog, CStdString("Th") + threadIdString + " processing: " + audioTapeRef->GetIdentifier()); + + AudioFileRef fileRef = audioTapeRef->GetAudioFileRef(); + fileRef->MoveOrig(); + fileRef->Open(AudioFile::READ); + + AudioChunkRef chunkRef; + AudioFileRef outFileRef; + + switch(CONFIG.m_storageAudioFormat) + { + case AudioTape::FfUlaw: + outFileRef.reset(new LibSndFileFile(SF_FORMAT_ULAW | SF_FORMAT_WAV)); + break; + case AudioTape::FfAlaw: + outFileRef.reset(new LibSndFileFile(SF_FORMAT_ALAW | SF_FORMAT_WAV)); + break; + case AudioTape::FfGsm: + default: + outFileRef.reset(new LibSndFileFile(SF_FORMAT_GSM610 | SF_FORMAT_WAV)); + } + CStdString file = CONFIG.m_audioOutputPath + "/" + audioTapeRef->GetPath() + audioTapeRef->GetIdentifier(); + outFileRef->Open(file, AudioFile::WRITE); + + while(fileRef->ReadChunkMono(chunkRef)) + { + outFileRef->WriteChunk(chunkRef); + } + + if(CONFIG.m_deleteNativeFile) + { + fileRef->Close(); + fileRef->Delete(); + CStdString threadIdString = IntToString(threadId); + LOG4CXX_INFO(LOG.batchProcessingLog, CStdString("Th") + threadIdString + " deleting native: " + audioTapeRef->GetIdentifier()); + } } } catch (CStdString& e) @@ -100,8 +113,8 @@ void BatchProcessing::ThreadHandler(void *args) catch(...) { } - } + LOG4CXX_INFO(LOG.batchProcessingLog, CStdString("Exiting thread #" + threadIdString)); } diff --git a/orkaudio/CapturePluginProxy.cpp b/orkaudio/CapturePluginProxy.cpp index 7c4acbc..02a79c0 100644 --- a/orkaudio/CapturePluginProxy.cpp +++ b/orkaudio/CapturePluginProxy.cpp @@ -14,6 +14,7 @@ #include "CapturePluginProxy.h" #include "ace/OS_NS_dirent.h" #include "ace/OS_NS_string.h" +#include "ace/Thread_Manager.h" #include "ConfigManager.h" #include "CapturePort.h" @@ -83,9 +84,11 @@ bool CapturePluginProxy::Initialize() else { // Ok, the dll has been successfully loaded + LOG4CXX_INFO(LOG.rootLog, CStdString("Loaded plugin: ") + pluginPath); + RegisterCallBacksFunction registerCallBacks; registerCallBacks = (RegisterCallBacksFunction)m_dll.symbol("RegisterCallBacks"); - registerCallBacks(AudioChunkCallBack, CaptureEventCallBack, LogManagerSingleton::instance()); + registerCallBacks(AudioChunkCallBack, CaptureEventCallBack, OrkLogManagerSingleton::instance()); m_configureFunction = (ConfigureFunction)m_dll.symbol("Configure"); if (m_configureFunction) @@ -144,7 +147,24 @@ bool CapturePluginProxy::Initialize() void CapturePluginProxy::Run() { - m_runFunction(); + if (!ACE_Thread_Manager::instance()->spawn(ACE_THR_FUNC(m_runFunction))) + { + LOG4CXX_INFO(LOG.rootLog, CStdString("Failed to create capture thread")); + } +} + +void CapturePluginProxy::Shutdown() +{ + ShutdownFunction shutdownFunction = (ShutdownFunction)m_dll.symbol("Shutdown"); + if (shutdownFunction) + { + LOG4CXX_INFO(LOG.rootLog, CStdString("Shutting down")); + shutdownFunction(); + } + else + { + LOG4CXX_INFO(LOG.rootLog, CStdString("Could not find DLL Shutdown function")); + } } void CapturePluginProxy::StartCapture(CStdString& capturePort) diff --git a/orkaudio/CapturePluginProxy.h b/orkaudio/CapturePluginProxy.h index 1efc520..1d1da1a 100644 --- a/orkaudio/CapturePluginProxy.h +++ b/orkaudio/CapturePluginProxy.h @@ -26,6 +26,7 @@ public: CapturePluginProxy(); bool Initialize(); void Run(); + void Shutdown(); void StartCapture(CStdString& capturePort); void StopCapture(CStdString& capturePort); diff --git a/orkaudio/Daemon.cpp b/orkaudio/Daemon.cpp index f834a7a..ed7e5a6 100644 --- a/orkaudio/Daemon.cpp +++ b/orkaudio/Daemon.cpp @@ -57,6 +57,8 @@ void Daemon::Initialize(CStdString serviceName, DaemonHandler runHandler, Daemon m_runHandler = runHandler; m_stopHandler = stopHandler; m_serviceName = serviceName; + + m_stopping = false; } void Daemon::Start() @@ -139,6 +141,7 @@ void Daemon::Run() void Daemon::Stop() { + m_stopping = true; m_stopHandler(); } @@ -192,3 +195,8 @@ void Daemon::Uninstall() #endif } +bool Daemon::IsStopping() +{ + return m_stopping; +} + diff --git a/orkaudio/Daemon.h b/orkaudio/Daemon.h index e19fff7..352b311 100644 --- a/orkaudio/Daemon.h +++ b/orkaudio/Daemon.h @@ -29,6 +29,7 @@ public: void Stop(); void Install(); void Uninstall(); + bool IsStopping(); private: #ifdef WIN32 static void WINAPI Run( DWORD /*argc*/, TCHAR* /*argv*/[] ); @@ -39,6 +40,8 @@ private: DaemonHandler m_runHandler; DaemonHandler m_stopHandler; CStdString m_serviceName; + + bool m_stopping; }; typedef ACE_Singleton DaemonSingleton; diff --git a/orkaudio/ImmediateProcessing.cpp b/orkaudio/ImmediateProcessing.cpp index 197f505..26f564e 100644 --- a/orkaudio/ImmediateProcessing.cpp +++ b/orkaudio/ImmediateProcessing.cpp @@ -15,6 +15,7 @@ #include "LogManager.h" #include "ace/OS_NS_unistd.h" #include "BatchProcessing.h" +#include "Daemon.h" ImmediateProcessing ImmediateProcessing::m_immediateProcessingSingleton; @@ -36,19 +37,32 @@ void ImmediateProcessing::ThreadHandler(void *args) { ImmediateProcessing* pImmediateProcessing = ImmediateProcessing::GetInstance(); - for(;;) + bool stop = false; + + for(;stop == false;) { try { AudioTapeRef audioTapeRef = pImmediateProcessing->m_audioTapeQueue.pop(); - //LOG4CXX_DEBUG(LOG.immediateProcessingLog, CStdString("Got chunk")); - - audioTapeRef->Write(); - if (audioTapeRef->IsStoppedAndValid()) + if(audioTapeRef.get() == NULL) + { + if(DaemonSingleton::instance()->IsStopping()) + { + stop = true; + } + } + else { - // Forward to batch processing thread - BatchProcessing::GetInstance()->AddAudioTape(audioTapeRef); + //LOG4CXX_DEBUG(LOG.immediateProcessingLog, CStdString("Got chunk")); + + audioTapeRef->Write(); + + if (audioTapeRef->IsStoppedAndValid()) + { + // Forward to batch processing thread + BatchProcessing::GetInstance()->AddAudioTape(audioTapeRef); + } } } catch (CStdString& e) @@ -56,6 +70,7 @@ void ImmediateProcessing::ThreadHandler(void *args) LOG4CXX_ERROR(LOG.immediateProcessingLog, CStdString("ImmediateProcessing: ") + e); } } + LOG4CXX_INFO(LOG.immediateProcessingLog, CStdString("Exiting thread")); } diff --git a/orkaudio/LogManager.cpp b/orkaudio/LogManager.cpp index 6639c98..d22589a 100644 --- a/orkaudio/LogManager.cpp +++ b/orkaudio/LogManager.cpp @@ -16,8 +16,9 @@ #include "LogManager.h" #include #include +#include -void LogManager::Initialize() +void OrkLogManager::Initialize() { BasicConfigurator::configure(); @@ -35,3 +36,8 @@ void LogManager::Initialize() tapelistLog = Logger::getLogger("tapelist"); } +void OrkLogManager::Shutdown() +{ + log4cxx::LogManager::shutdown(); +} + diff --git a/orkaudio/LogManager.h b/orkaudio/LogManager.h index e605aa5..2556147 100644 --- a/orkaudio/LogManager.h +++ b/orkaudio/LogManager.h @@ -20,10 +20,11 @@ using namespace log4cxx; -class LogManager +class OrkLogManager { public: void Initialize(); + void Shutdown(); LoggerPtr rootLog; LoggerPtr topLog; @@ -36,9 +37,9 @@ public: LoggerPtr tapelistLog; }; -typedef ACE_Singleton LogManagerSingleton; +typedef ACE_Singleton OrkLogManagerSingleton; -#define LOG (*LogManagerSingleton::instance()) +#define LOG (*OrkLogManagerSingleton::instance()) #endif diff --git a/orkaudio/OrkAudio.cpp b/orkaudio/OrkAudio.cpp index 45a1434..75e1140 100644 --- a/orkaudio/OrkAudio.cpp +++ b/orkaudio/OrkAudio.cpp @@ -42,9 +42,16 @@ void StopHandler() serviceStop = true; } +#ifdef WIN32 +long ExceptionFilter(struct _EXCEPTION_POINTERS *ptr) +{ + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + void MainThread() { - LogManagerSingleton::instance()->Initialize(); + OrkLogManagerSingleton::instance()->Initialize(); LOG4CXX_INFO(LOG.rootLog, CStdString("\n\nOrkAudio service starting\n")); // Initialize object factory and register existing objects @@ -100,11 +107,27 @@ void MainThread() } //ACE_Thread_Manager::instance ()->wait (); - while(serviceStop == false) + while(!DaemonSingleton::instance()->IsStopping()) { ACE_OS::sleep(1); } - LOG4CXX_INFO(LOG.rootLog, CStdString("Stopping service")); + + CapturePluginProxySingleton::instance()->Shutdown(); + + // Wait that all ACE threads have returned + //ACE_Thread_Manager::instance ()->wait (); + ACE_OS::sleep(2); + + //***** This is to avoid an exception when NT service exiting + //***** Need to find out the real problem and fix +#ifdef WIN32 + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ExceptionFilter); +#endif + //***** + + LOG4CXX_INFO(LOG.rootLog, CStdString("Service stopped")); + OrkLogManagerSingleton::instance()->Shutdown(); } diff --git a/orkaudio/Reporting.cpp b/orkaudio/Reporting.cpp index 1360dfe..2ffb180 100644 --- a/orkaudio/Reporting.cpp +++ b/orkaudio/Reporting.cpp @@ -16,6 +16,8 @@ #include "LogManager.h" #include "messages/Message.h" #include "OrkClient.h" +#include "Daemon.h" + Reporting Reporting::m_reportingSingleton; @@ -35,31 +37,51 @@ void Reporting::AddAudioTape(AudioTapeRef audioTapeRef) void Reporting::ThreadHandler(void *args) { Reporting* pReporting = Reporting::GetInstance(); + bool stop = false; - for(;;) + for(;stop == false;) { - AudioTapeRef audioTapeRef = pReporting->m_audioTapeQueue.pop(); - - MessageRef msgRef; - audioTapeRef->GetMessage(msgRef); - if(msgRef.get() && CONFIG.m_enableReporting) + try { - CStdString msgAsSingleLineString = msgRef->SerializeSingleLine(); - LOG4CXX_INFO(LOG.reportingLog, msgAsSingleLineString); + AudioTapeRef audioTapeRef = pReporting->m_audioTapeQueue.pop(); - OrkHttpSingleLineClient c; - SimpleResponseMsg srm; - while (!c.Execute((SyncMessage&)(*msgRef.get()), srm, CONFIG.m_trackerHostname, CONFIG.m_trackerTcpPort, CONFIG.m_trackerServicename, CONFIG.m_clientTimeout)) + if(audioTapeRef.get() == NULL) + { + if(DaemonSingleton::instance()->IsStopping()) + { + stop = true; + } + } + else { - ACE_OS::sleep(5); + + MessageRef msgRef; + audioTapeRef->GetMessage(msgRef); + if(msgRef.get() && CONFIG.m_enableReporting) + { + CStdString msgAsSingleLineString = msgRef->SerializeSingleLine(); + LOG4CXX_INFO(LOG.reportingLog, msgAsSingleLineString); + + OrkHttpSingleLineClient c; + SimpleResponseMsg srm; + while (!c.Execute((SyncMessage&)(*msgRef.get()), srm, CONFIG.m_trackerHostname, CONFIG.m_trackerTcpPort, CONFIG.m_trackerServicename, CONFIG.m_clientTimeout)) + { + ACE_OS::sleep(5); + } + //CStdString host("foo"); + //while (!msgRef->InvokeXmlRpc(host, 10000)) + //{ + // ACE_OS::sleep(5); + //} + } } - //CStdString host("foo"); - //while (!msgRef->InvokeXmlRpc(host, 10000)) - //{ - // ACE_OS::sleep(5); - //} + } + catch (CStdString& e) + { + LOG4CXX_ERROR(LOG.reportingLog, CStdString("Exception: ") + e); } } + LOG4CXX_INFO(LOG.reportingLog, CStdString("Exiting thread")); } diff --git a/orkaudio/ThreadSafeQueue.h b/orkaudio/ThreadSafeQueue.h index 4fcc330..e050c85 100644 --- a/orkaudio/ThreadSafeQueue.h +++ b/orkaudio/ThreadSafeQueue.h @@ -61,13 +61,17 @@ template bool ThreadSafeQueue::push(T &element) /** Pop and element from the queue, or blocks until one available */ template T ThreadSafeQueue::pop() { - m_semaphore.acquire(); - + ACE_Time_Value timeout(time(NULL)+2); + m_semaphore.acquire(&timeout); MutexSentinel mutexSentinel(m_mutex); - T element = m_queue.front(); - m_queue.pop(); + T element; + if(m_queue.size() > 0) + { + element = m_queue.front(); + m_queue.pop(); + } return element; } diff --git a/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.cpp b/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.cpp index 31c8503..ca35e51 100644 --- a/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.cpp +++ b/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.cpp @@ -19,9 +19,9 @@ AudioChunkCallBackFunction g_audioChunkCallBack; CaptureEventCallBackFunction g_captureEventCallBack; -LogManager* g_logManager; +OrkLogManager* g_logManager; -void __CDECL__ RegisterCallBacks(AudioChunkCallBackFunction audioCallBack, CaptureEventCallBackFunction captureEventCallBack, LogManager* logManager) +void __CDECL__ RegisterCallBacks(AudioChunkCallBackFunction audioCallBack, CaptureEventCallBackFunction captureEventCallBack, OrkLogManager* logManager) { g_audioChunkCallBack = audioCallBack; g_captureEventCallBack = captureEventCallBack; diff --git a/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.h b/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.h index b7940ef..951e097 100644 --- a/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.h +++ b/orkaudio/audiocaptureplugins/common/AudioCapturePluginCommon.h @@ -25,9 +25,10 @@ // Shared library exports extern "C" // to avoid function name decoration, makes them easier to lookup { -DLL_EXPORT void __CDECL__ RegisterCallBacks(AudioChunkCallBackFunction, CaptureEventCallBackFunction, LogManager*); +DLL_EXPORT void __CDECL__ RegisterCallBacks(AudioChunkCallBackFunction, CaptureEventCallBackFunction, OrkLogManager*); DLL_EXPORT void __CDECL__ Run(); DLL_EXPORT void __CDECL__ Initialize(); +DLL_EXPORT void __CDECL__ Shutdown(); DLL_EXPORT void __CDECL__ Configure(DOMNode*); DLL_EXPORT void __CDECL__ StartCapture(CStdString& capturePort); DLL_EXPORT void __CDECL__ StopCapture(CStdString& capturePort); diff --git a/orkaudio/audiocaptureplugins/generator/Generator.cpp b/orkaudio/audiocaptureplugins/generator/Generator.cpp index 77bfdf9..8deb07a 100644 --- a/orkaudio/audiocaptureplugins/generator/Generator.cpp +++ b/orkaudio/audiocaptureplugins/generator/Generator.cpp @@ -21,7 +21,7 @@ extern AudioChunkCallBackFunction g_audioChunkCallBack; extern CaptureEventCallBackFunction g_captureEventCallBack; -extern LogManager* g_logManager; +extern OrkLogManager* g_logManager; GeneratorConfigTopObjectRef g_generatorConfigTopObjectRef; #define GCONFIG g_generatorConfigTopObjectRef.get()->m_config diff --git a/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp index 2a6bef4..4252f0d 100644 --- a/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp +++ b/orkaudio/audiocaptureplugins/sounddevice/SoundDevice.cpp @@ -24,7 +24,7 @@ extern AudioChunkCallBackFunction g_audioChunkCallBack; extern CaptureEventCallBackFunction g_captureEventCallBack; -extern LogManager* g_logManager; +extern OrkLogManager* g_logManager; SoundDeviceConfigTopObjectRef g_soundDeviceConfigTopObjectRef; #define DLLCONFIG g_soundDeviceConfigTopObjectRef.get()->m_config diff --git a/orkaudio/audiocaptureplugins/voip/VoIp.cpp b/orkaudio/audiocaptureplugins/voip/VoIp.cpp index adc21da..ea23fb1 100644 --- a/orkaudio/audiocaptureplugins/voip/VoIp.cpp +++ b/orkaudio/audiocaptureplugins/voip/VoIp.cpp @@ -30,7 +30,7 @@ extern AudioChunkCallBackFunction g_audioChunkCallBack; extern CaptureEventCallBackFunction g_captureEventCallBack; -extern LogManager* g_logManager; +extern OrkLogManager* g_logManager; #include "LogManager.h" @@ -384,6 +384,7 @@ public: VoIp(); void Initialize(); void Run(); + void Shutdown(); void StartCapture(CStdString& port); void StopCapture(CStdString& port); private: @@ -523,6 +524,12 @@ void VoIp::Run() } } +void VoIp::Shutdown() +{ + LOG4CXX_INFO(s_log, "Shutting down VoIp.dll"); + pcap_breakloop(m_pcapHandle); +} + void VoIp::StartCapture(CStdString& port) { ; @@ -543,6 +550,11 @@ void __CDECL__ Run() VoIpSingleton::instance()->Run(); } +void __CDECL__ Shutdown() +{ + VoIpSingleton::instance()->Shutdown(); +} + void __CDECL__ StartCapture(CStdString& capturePort) { ; -- cgit v1.2.3