Resolve fix:

- CancelResolv(): Standard function to cancel name resolve requests
  - Allow Resolv request to complete if not cancelled
  - Clear memory if resolve request cancelled
- getaddrinfo_a(): still leaks if thread not closed
Other:
- Code clean up
This commit is contained in:
2022-07-21 12:08:22 +02:00
parent 1c81055eea
commit fd3738567a
6 changed files with 85 additions and 90 deletions

View File

@@ -65,8 +65,7 @@ CApplication::~CApplication()
TFunctionType * NextType; TFunctionType * NextType;
// Destroy functions // Destroy functions
while (FirstFunction) while (FirstFunction) {
{
NextFunction = FirstFunction->Next; NextFunction = FirstFunction->Next;
delete( FirstFunction->Function ); delete( FirstFunction->Function );
free( FirstFunction ); free( FirstFunction );
@@ -74,8 +73,7 @@ CApplication::~CApplication()
} }
// Destroy function types // Destroy function types
while (FirstFunctionType) while (FirstFunctionType) {
{
NextType = FirstFunctionType->Next; NextType = FirstFunctionType->Next;
free( FirstFunctionType->Name ); free( FirstFunctionType->Name );
free( FirstFunctionType ); free( FirstFunctionType );
@@ -116,8 +114,7 @@ void CApplication::GetProcessName( char ** ProcessName, char * pFilePath )
bool CApplication::ReadParam( int argc, char *argv[] ) bool CApplication::ReadParam( int argc, char *argv[] )
{ {
// Read Parameters // Read Parameters
if ((argc != 2)) if ((argc != 2)) {
{
// Get Process Name // Get Process Name
GetProcessName( &ProcessName, argv[0] ); GetProcessName( &ProcessName, argv[0] );
@@ -126,8 +123,7 @@ bool CApplication::ReadParam( int argc, char *argv[] )
printf( " usage: %s [ConfigFile]\n\n", ProcessName ); printf( " usage: %s [ConfigFile]\n\n", ProcessName );
return false; return false;
} }
else else {
{
// Load parameters // Load parameters
GetProcessName( &ProcessName, argv[1] ); GetProcessName( &ProcessName, argv[1] );
ConfigFile = argv[1]; ConfigFile = argv[1];

View File

@@ -39,8 +39,7 @@ struct SFunctionType {
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
struct SFunctionItem struct SFunctionItem {
{
CFunctionCore * Function; CFunctionCore * Function;
SFunctionItem * Next; SFunctionItem * Next;
}; };

View File

@@ -51,8 +51,7 @@ CSelect::~CSelect()
TSelectHandle * NextHandle; TSelectHandle * NextHandle;
// Destroy handles // Destroy handles
while (FirstHandle) while (FirstHandle) {
{
NextHandle = FirstHandle->Next; NextHandle = FirstHandle->Next;
delete FirstHandle; delete FirstHandle;
FirstHandle = NextHandle; FirstHandle = NextHandle;
@@ -197,8 +196,7 @@ bool CSelect::Test()
// Perform select // Perform select
Events = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &STimeout ); Events = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &STimeout );
if (Events < 0) if (Events < 0) {
{
if (Log) Log->Message( LogLevel, dlHigh, "%s/Selector: Select operation failed", ProcessName ); if (Log) Log->Message( LogLevel, dlHigh, "%s/Selector: Select operation failed", ProcessName );
return false; return false;
} }
@@ -206,11 +204,9 @@ bool CSelect::Test()
// Check all descriptors for events // Check all descriptors for events
if (Events) { if (Events) {
Handle = FirstHandle; Handle = FirstHandle;
while (Handle) while (Handle) {
{
// Check if to remove from list // Check if to remove from list
if (!Handle->Read && !Handle->Write) if (!Handle->Read && !Handle->Write) {
{
// Update Maximum Test FD // Update Maximum Test FD
if (Handle->FD == MaxFD-1) { if (Handle->FD == MaxFD-1) {
for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) { for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) {
@@ -232,18 +228,15 @@ bool CSelect::Test()
Handle = *HandlePtr; Handle = *HandlePtr;
continue; continue;
} }
else else {
{
// Check read Event // Check read Event
if (FD_ISSET( Handle->FD, &ReadFDS ) && Handle->Function) { if (FD_ISSET( Handle->FD, &ReadFDS ) && Handle->Function)
Handle->Function->Read( Handle->FD ); Handle->Function->Read( Handle->FD );
}
// Check Write Event // Check Write Event
if (FD_ISSET( Handle->FD, &WriteFDS ) && Handle->Function) { if (FD_ISSET( Handle->FD, &WriteFDS ) && Handle->Function)
Handle->Function->Write( Handle->FD ); Handle->Function->Write( Handle->FD );
} }
}
// Next // Next
Handle = Handle->Next; Handle = Handle->Next;
} }

View File

@@ -74,24 +74,17 @@ CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSe
CSelectableCore::~CSelectableCore() CSelectableCore::~CSelectableCore()
{ {
THandle * NextHandle = NULL; THandle * NextHandle = NULL;
bool Result;
// Destroy File Handles // Destroy File Handles
while (FirstHandle) { while (FirstHandle) {
// Close active resolve request // Cancel pending resolve request
if (FirstHandle->ResolveReq) { CancelResolve( FirstHandle );
if ((Result = gai_cancel( FirstHandle->ResolveReq->Request )) != 0) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error canceling Host Name resolve [%s:%s] (%s)",
ProcessName, Name, FirstHandle->Name, FirstHandle->HostName, FirstHandle->PortName, gai_strerror(Result) );
DestroyResolveReq( FirstHandle, true );
HandleState( FirstHandle, csFailed );
}
}
// Close handle if open // Close handle if open
if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen)) if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen))
Close( FirstHandle, false ); Close( FirstHandle, false );
// Destroy handle
NextHandle = FirstHandle->Next; NextHandle = FirstHandle->Next;
DestroyHandle( FirstHandle ); DestroyHandle( FirstHandle );
FirstHandle = NextHandle; FirstHandle = NextHandle;
@@ -286,20 +279,12 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
bool CSelectableCore::DestroyHandle( THandle * Handle ) bool CSelectableCore::DestroyHandle( THandle * Handle )
{ {
int Result;
// Validate Handle // Validate Handle
if (!Handle) if (!Handle)
return false; return false;
// Destroy Resolve request // Cancel pending resolve request
if (Handle->ResolveReq) { CancelResolve( Handle );
if ((Result = gai_cancel( Handle->ResolveReq->Request )) != 0) {
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error canceling Host Name resolve [%s:%s] (%s)",
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(Result) );
}
DestroyResolveReq( Handle, true );
}
// Clear parameters // Clear parameters
if (Handle->Name) if (Handle->Name)
@@ -1035,30 +1020,6 @@ bool CSelectableCore::ResolveAddress( THandle * Handle )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CSelectableCore::DestroyResolveReq( THandle * Handle, bool DestroyResult )
{
// Validate
if (!Handle || !Handle->ResolveReq)
return false;
// Destroy
if (DestroyResult) {
if (Handle->ResolveReq->Request->ar_result)
freeaddrinfo( Handle->ResolveReq->Request->ar_result );
}
if (Handle->ResolveReq->Request->ar_request)
free( (void*)Handle->ResolveReq->Request->ar_request );
if (Handle->ResolveReq->Request)
free( Handle->ResolveReq->Request );
if (Handle->ResolveReq)
delete Handle->ResolveReq;
// Reset request
Handle->ResolveReq = NULL;
return true;
}
//---------------------------------------------------------------------------
bool CSelectableCore::HandleResolve( THandle * Handle ) bool CSelectableCore::HandleResolve( THandle * Handle )
{ {
bool Result; bool Result;
@@ -1107,6 +1068,59 @@ bool CSelectableCore::HandleResolve( THandle * Handle )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool CSelectableCore::CancelResolve( THandle * Handle )
{
int Result;
int WaitCnt = 0;
// Check if request pending
if (!Handle->ResolveReq)
return true;
// Cancel request
Result = gai_cancel( FirstHandle->ResolveReq->Request );
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Cancelling Host Name resolve [%s:%s] (%s)",
ProcessName, Name, FirstHandle->Name, FirstHandle->HostName, FirstHandle->PortName, gai_strerror(Result) );
if (Result == EAI_CANCELED) {
// Clear request
DestroyResolveReq( Handle, true );
}
else if (Result == EAI_NOTCANCELED) {
// Allow request to return
while (FirstHandle->ResolveReq && (WaitCnt < 1000)) {
WaitCnt++;
usleep(1000);
}
}
return true;
}
//---------------------------------------------------------------------------
bool CSelectableCore::DestroyResolveReq( THandle * Handle, bool DestroyResult )
{
// Validate
if (!Handle || !Handle->ResolveReq)
return false;
// Destroy resolv request
if (Handle->ResolveReq->Request) {
if (DestroyResult && Handle->ResolveReq->Request->ar_result)
freeaddrinfo( Handle->ResolveReq->Request->ar_result );
if (Handle->ResolveReq->Request->ar_request)
free( (void*)Handle->ResolveReq->Request->ar_request );
if (Handle->ResolveReq->Request)
free( Handle->ResolveReq->Request );
}
// Reset request
if (Handle->ResolveReq)
delete Handle->ResolveReq;
Handle->ResolveReq = NULL;
return true;
}
//---------------------------------------------------------------------------
THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle ) THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle )
{ {
// Validate Handle // Validate Handle

View File

@@ -313,6 +313,7 @@ protected:
// Socket Operations // Socket Operations
bool ResolveAddress( THandle * Handle ); bool ResolveAddress( THandle * Handle );
bool HandleResolve( THandle * Handle ); bool HandleResolve( THandle * Handle );
bool CancelResolve( THandle * Handle );
bool DestroyResolveReq( THandle * Handle, bool DestroyResult ); bool DestroyResolveReq( THandle * Handle, bool DestroyResult );
// Managing File Handles // Managing File Handles

View File

@@ -65,8 +65,7 @@ void SignalTerminate( int sig )
char SigName[10]; char SigName[10];
// Determine signal name // Determine signal name
switch (sig) switch (sig) {
{
case SIGHUP : strcpy( SigName, "SIGHUP " ); break; case SIGHUP : strcpy( SigName, "SIGHUP " ); break;
case SIGINT : strcpy( SigName, "SIGINT " ); break; case SIGINT : strcpy( SigName, "SIGINT " ); break;
case SIGQUIT : strcpy( SigName, "SIGQUIT" ); break; case SIGQUIT : strcpy( SigName, "SIGQUIT" ); break;
@@ -82,36 +81,30 @@ void SignalTerminate( int sig )
std::cerr << std::endl << ProcessName << ": ***********************************" << std::endl; std::cerr << std::endl << ProcessName << ": ***********************************" << std::endl;
// Create Application->Log Entry // Create Application->Log Entry
if (Application->Log) if (Application->Log) {
{
Application->Log->Message( dlLow, dlLow, "%s: ** %s signal received [%d] **", ProcessName, SigName, TermCount ); Application->Log->Message( dlLow, dlLow, "%s: ** %s signal received [%d] **", ProcessName, SigName, TermCount );
// Check for Terminate Limit // Check for Terminate Limit
if (TermCount < MaxTermCount) { if (TermCount < MaxTermCount)
Application->Log->Message( dlLow, dlLow, "%s: ** Terminating normally... **", ProcessName ); Application->Log->Message( dlLow, dlLow, "%s: ** Terminating normally... **", ProcessName );
} else { else
Application->Log->Message( dlLow, dlLow, "%s: ** Terminating immediately! **", ProcessName ); Application->Log->Message( dlLow, dlLow, "%s: ** Terminating immediately! **", ProcessName );
} }
} else {
else
{
std::cerr << ProcessName << ": ** " << SigName << " signal received [" << TermCount << "] **" << std::endl; std::cerr << ProcessName << ": ** " << SigName << " signal received [" << TermCount << "] **" << std::endl;
// Check for Terminate Limit // Check for Terminate Limit
if (TermCount < MaxTermCount) { if (TermCount < MaxTermCount)
std::cerr << ProcessName << ": ** Terminating normally... **" << std::endl; std::cerr << ProcessName << ": ** Terminating normally... **" << std::endl;
} else { else
std::cerr << ProcessName << ": ** Terminating immediately! **" << std::endl; std::cerr << ProcessName << ": ** Terminating immediately! **" << std::endl;
} }
}
std::cerr << ProcessName << ": ***********************************" << std::endl << std::endl; std::cerr << ProcessName << ": ***********************************" << std::endl << std::endl;
// Check for Terminate Limit // Check for Terminate Limit
if (TermCount >= MaxTermCount) { if (TermCount >= MaxTermCount)
exit( sig ); exit( sig );
} }
//---------------------------------------------------------------------------
return;
}//---------------------------------------------------------------------------
// Signal Handler to terminate program immediately // Signal Handler to terminate program immediately
void SignalAbort( int sig ) void SignalAbort( int sig )
@@ -119,8 +112,7 @@ void SignalAbort( int sig )
char SigName[10]; char SigName[10];
// Determine Signal name // Determine Signal name
switch (sig) switch (sig) {
{
case SIGABRT : strcpy( SigName, "SIGABRT" ); break; case SIGABRT : strcpy( SigName, "SIGABRT" ); break;
case SIGFPE : strcpy( SigName, "SIGFPE " ); break; case SIGFPE : strcpy( SigName, "SIGFPE " ); break;
case SIGILL : strcpy( SigName, "SIGILL " ); break; case SIGILL : strcpy( SigName, "SIGILL " ); break;