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:
@@ -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];
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ struct SFunctionType {
|
|||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
struct SFunctionItem
|
struct SFunctionItem {
|
||||||
{
|
|
||||||
CFunctionCore * Function;
|
CFunctionCore * Function;
|
||||||
SFunctionItem * Next;
|
SFunctionItem * Next;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,17 +228,14 @@ 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;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSe
|
|||||||
// Configure resolve signal handler
|
// Configure resolve signal handler
|
||||||
ResolveAct.sa_sigaction = &ResolveHandler;
|
ResolveAct.sa_sigaction = &ResolveHandler;
|
||||||
sigemptyset( &ResolveAct.sa_mask );
|
sigemptyset( &ResolveAct.sa_mask );
|
||||||
ResolveAct.sa_flags = SA_SIGINFO;
|
ResolveAct.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
sigaction( SIGRTMIN, &ResolveAct, NULL );
|
sigaction( SIGRTMIN, &ResolveAct, NULL );
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
@@ -1002,8 +987,8 @@ bool CSelectableCore::ResolveAddress( THandle * Handle )
|
|||||||
ResolveReq = new TResolveReq;
|
ResolveReq = new TResolveReq;
|
||||||
Handle->ResolveReq = ResolveReq;
|
Handle->ResolveReq = ResolveReq;
|
||||||
|
|
||||||
ResolveReq->Handle = Handle;
|
ResolveReq->Handle = Handle;
|
||||||
ResolveReq->Request = (gaicb*)calloc( 1, sizeof(gaicb) );
|
ResolveReq->Request = (gaicb*)calloc( 1, sizeof(gaicb) );
|
||||||
|
|
||||||
// DNS request / reply structure
|
// DNS request / reply structure
|
||||||
ResolveReq->Request->ar_name = Handle->HostName;
|
ResolveReq->Request->ar_name = Handle->HostName;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user