HANDLE leak bei timeout funktion für connect() call
-
Habe ein connection timeout für connect() gebastelt. Funktioniert auch alles, doch habe ich HANDLE leak's. Habe jetzt fast 2 stunden gesucht und probiert und probiert... alles gedebuggt und komme einfach nicht weiter! Finde es nicht gebe auch alle HANDLES und socket's wieder frei!
Bei diesem bsp. habe ich immer pro port scan (also pro schleifen durchlauf) 2 HANDLES die nicht frigegeben werden. Also pro durchlauf kommen immer 2 HANDLES dazu. Dies habe ich per taskmanager ermittelt.
Vielleicht kann mir einer helfen!?
MAIN:
#include <winsock2.h> #include <windows.h> #include <stdio.h> #include <time.h> #include "netlib.h" int main(void) { SOCKET csock = 0; SOCKADDR_IN addr = {0}; unsigned short port; char dest_host[]={"172.16.0.2"}; // dest ip /* Init winsock2.lib */ if( InitWinSock2() ) { return 1; } for(port=0;port<60;port++) { if( TcpConnectTo(dest_host ,&csock ,&addr ,port ,500) ) { printf_s("port %i closed\n",port); } else { printf_s("port %i open\n",port); closesocket(csock); } } printf_s("Exit...\n"); getchar(); WSACleanup(); return 0; }NETLIB.C
/* connect call wrapping structure for connection timeout */ typedef struct { SOCKET sock; SOCKADDR_IN addr; int lenaddr; } CONNECT_INFO; /* connect call wrapping thread for connection timeout */ DWORD WINAPI ConnectThread(CONNECT_INFO *construct); int GetAddrFromStr(char *iporname, SOCKADDR_IN *addr_struct) { HOSTENT *header = 0; unsigned long ip = 0; if(iporname == NULL || addr_struct == NULL) { return 1; } ip = inet_addr(iporname); if(ip != INADDR_NONE) { addr_struct->sin_addr.s_addr = ip; return 0; } else { header = gethostbyname(iporname); if(header == NULL) { return 1; } else { memcpy(&(addr_struct->sin_addr) ,header->h_addr_list[0] ,4); } } return 0; } int InitWinSock2(void) { WSADATA iws; if( WSAStartup(MAKEWORD(2,2), &iws) != 0 ) { #ifdef OUTPUT_ON printf("\nWSAStartup() error : %i\n",WSAGetLastError()); #endif return 1; } return 0; } DWORD WINAPI ConnectThread(CONNECT_INFO *construct) { int rc = 0; rc = connect(construct->sock ,(SOCKADDR*)&construct->addr ,sizeof(SOCKADDR)); if(rc == SOCKET_ERROR) { #ifdef OUTPUT_ON printf("TcpConnectTo -> connect(), error code :%i\n",WSAGetLastError()); #endif ExitThread(1); } ExitThread(0); } int TcpConnectTo(char *host_str ,SOCKET *p_sock ,SOCKADDR_IN *addr_struct ,unsigned short port ,int connection_timeout_msec) { int rc = 0 ,request = 0; SOCKET sock = 0; HANDLE ConnectHandle = NULL; DWORD ThreadId = 0 ,sig = 0 ,exitcode = 0; SOCKADDR_IN tmp_addr_struct = {0}; CONNECT_INFO connect_info = {0}; /* Create and define socket */ sock = socket(AF_INET ,SOCK_STREAM ,0); if(sock == INVALID_SOCKET) { #ifdef OUTPUT_ON printf("TcpConnectTo -> socket(), error code :%i\n", WSAGetLastError()); #endif return 1; } /* Define address struct */ memset(&tmp_addr_struct,0,sizeof(SOCKADDR_IN)); tmp_addr_struct.sin_family = AF_INET; tmp_addr_struct.sin_port = htons(port); /* Resolve hostname from string */ request = GetAddrFromStr(host_str, &tmp_addr_struct); if(request) { #ifdef OUTPUT_ON printf("TcpConnectTo -> GetAddrFromStr(), error code :%i\n",WSAGetLastError()); #endif return 1; } /* Set CONNECT_INFO struct */ connect_info.sock = sock; memcpy(&connect_info.addr ,&tmp_addr_struct ,sizeof(tmp_addr_struct)); connect_info.lenaddr = sizeof(tmp_addr_struct); /* Connect to host - start connection thread */ ConnectHandle = CreateThread(NULL ,0 ,(LPTHREAD_START_ROUTINE)ConnectThread ,(CONNECT_INFO *)&connect_info ,0 ,&ThreadId); if(ConnectHandle == NULL) { if( ! CloseHandle(ConnectHandle) ) { printf("close handle failed 0\n"); } closesocket(sock); return 1; } /* Wait of the object-signal or timeout */ sig = WaitForSingleObject(ConnectHandle ,connection_timeout_msec); if(sig == WAIT_TIMEOUT) { if( ! TerminateThread(ConnectHandle ,1) ) { printf("terminate thread fail nr.1\n"); } if( ! CloseHandle(ConnectHandle) ) { printf("close handle failed 1\n"); } closesocket(sock); return 1; } GetExitCodeThread(ConnectHandle ,&exitcode); if(exitcode == 1) { if( ! TerminateThread(ConnectHandle ,1) ) { printf("terminate thread fail nr.2\n"); } if( ! CloseHandle(ConnectHandle) ) { printf("close handle failed 2\n"); } closesocket(sock); return 1; } if( ! TerminateThread(ConnectHandle ,0) ) { printf("terminate thread fail nr.3\n"); } if( ! CloseHandle(ConnectHandle) ) { printf("close handle failed 3\n"); } /* Set addr info */ *p_sock = connect_info.sock; memcpy(addr_struct ,&connect_info.addr ,sizeof(tmp_addr_struct)); return 0; }Hoffentlich habe ich nichts vergessen. Die netlib.h lass ich mal weg. Es funktioniert wie gesagt. Doch sind da eben diese HANDLE leak's wie beschrieben.
Ach ja wie ihr sehen könnt ist das ganze mit einem Thread gemacht der bei dem gewünschten timeout mit WaitForSingleObject() durch TerminateThread(ThreadHandle ,1) den thread abbricht. Wenn der Thread for dem timeout endet, ermittle ich mit GetExitCodeThread(ThreadHandle ,&exitcode); was der thread zurückgegeben hat!Ein bisschen viel sorry

-
Auch wenn es keine direkte Antwort auf deine Frage ist: Versuch eine Lösung ohne TerminateThread zu implementieren.
TerminateThread is a dangerous function that should only be used in the most extreme cases.
-
Wie kann ich den den Thread von der main() aus terminieren!? Wenn doch das timeout überschritten ist möchte ich den Thread abbrechen. Wenn TerminateThread eine schlechte Wahl ist, was soll ich dan benutzen?
-
Timeouts kannst du z.B. mit einem Non-Blocking Socket und select() implementieren.
-
Oo schrieb:
Timeouts kannst du z.B. mit einem Non-Blocking Socket und select() implementieren.
Ja das weis ich, aber ich möchte es so machen. Wäre _beginthread _endthreadex besser geeignet?
-
Oo schrieb:
Timeouts kannst du z.B. mit einem Non-Blocking Socket und select() implementieren.
Oder könntest Du mir ein kleines bsp. geben damit ich einen Anhaltspunkt habe! Denn ich kenne mich mit select() nicht aus. Denn Socket in den non-blocking Mode schalten ist kein Problem.
Wäre nett thx
-
Danke habe es jetz mit select() gemacht!