PDA

Visualizza la versione completa : [C] Problema grave con recv()


Manugal
01-03-2010, 17:19
Ciao a tutti!

Sono un po' di giorni che sto sbattendo la testa su un problema e non riesco a venirne a capo. Sto sviluppando un mail server multithread. Posto direttamente il codice (è molto lungo perciò ometterò alcune parti):



//MultiThreadedServer.c
static SOCKET POP3Socket = INVALID_SOCKET;
static SOCKET SMTPSocket = INVALID_SOCKET;

void MultiThreadedServer()
{
...
setWinSocket(); // Imposta i socket SMTP e POP3
while(TRUE){
hSMTP=(HANDLE)_beginthreadex(NULL,0,SMTPThrdConn,&tArgs[iThd+1],0,&SMTPThId);
tStatus = WaitForSingleObject(hSMTP,INFINITE);
if(tStatus==WAIT_OBJECT_0){
CloseHandle(hSMTP);
}
...
}

static DWORD WINAPI SMTPThrdConn(SRV_PARAMS *tArgs)
{
...
tArgs->SMTPSocket=accept(SMTPSocket,...);
tArgs->srv_hndl=(HANDLE)_beginthreadex (NULL, 0, SMTPCommands, tArgs, 0, &ThId);
...
}

// SMTPCommands.c
void SMTPCommands(SRV_PARAMS *tArgs)
{
...
char *tmpStr=(char *)calloc(MAX_REQ_SIZE,sizeof(char));
while (!session->Done && !flagsGuard.ReReadCfg){
session->request=(char *)calloc(MAX_REQ_SIZE,sizeof(char));
do{
memset(tmpStr,0,sizeof(tmpStr));
iResult=recv(tArgs->SMTPSocket,tmpStr,sizeof(tmpStr)-1,0);
if(iResult<0)
PrintError("recv() failed:");
strcat(session->request,tmpStr);
} while(strstr(tmpStr,"\n")==NULL);
...
}


Il problema è che la recv spesso ritorna -1 e il fatto ancora più strano è che GetLastError() ritorna 0. A schermo infatti mi stampa "recv() failed: Operazione completata".

Provando a fare un debugging con gdb al momento dell'errore digito bt e mi ritorna:


#0 SMTPCommands (tArgs=0x28fddc) at SMTPCommands.c:35 [dove controllo che iResult<0]
#1 0x77221287 in msvcrt!_itow_s () from C:\Windows\syswow64\msvcrt.dll
#2 0x77221328 in msvcrt!_endthreadex () from C:\Windows\syswow64\msvcrt.dll
#3 0x77123677 in KERNEL32!BasepMapModuleHandle ()
from C:\Windows\syswow64\kernel32.dll
#4 0x005b3770 in ?? ()
#5 0x029bffd4 in ?? ()
#6 0x77969d72 in ntdll!RtlpNtMakeTemporaryKey ()
from C:\Windows\system32\ntdll.dll
#7 0x005b3770 in ?? ()
#8 0x74145183 in ?? ()
#9 0x00000000 in ?? ()


Non riesco proprio a capire cos'è che non va.

oregon
01-03-2010, 17:29
Chiama la WSAGetLastError per ottenere il codice d'errore ...

Manugal
01-03-2010, 18:00
Non mi ero accorto di una cosa. Cioè prima di chiamare PrintError() chiamavo WSACleanup() e ovviamente l'operazione andava a buon fine e quindi mi restuiva 0. Ora il messaggio di errore corretto è: "recv failed(): parametro non corretto".

A cosa corrisponde?

Edit: Il codice d'errore è WSA_INVALID_PARAMETER.

Manugal
01-03-2010, 18:28
Ora che ho modificato il terzo parametro della recv() in MAX_REQ_SIZE (al posto di sizeof) non da più quell'errore ma ne da un altro. Se invio il primo comando non mi da problemi e il mio server risponde correttamente, ma come invio il secondo comando mi ritorna: "recv() failed: Tentativo di operazione su un elemento diverso dal socket - Error Code: WSAENOTSOCK".

Potrebbe dipendere dal fatto che SMTPSocket è dichiarata globale in MultiThreadServer.c?

oregon
01-03-2010, 18:35
L'errore fa riferimento al parametro

tArgs->SMTPSocket

che non viene ritenuto un socket valido.

Dato che la prima volta mi sembra che funzioni, allora penso che la cosa più probabile sia che avviene una "corruzione" della memoria (dopo la ricezione), che modifica il valore del socket rendendolo non valido.

Ma non è possibile dirti di piu' "a distanza" ... ti consiglio un debugging "profondo" del codice ...

Manugal
01-03-2010, 19:05
Investigherò ulteriormente sul problema, grazie.

Manugal
01-03-2010, 19:18
Credo di aver risolto.

In pratica io ho un thread apposito per accettare le connessioni SMTP e POP3. Quando arriva una connessione il thread termina e ne riparte un altro per accettare una nuova connessione. Il problema stava nel fatto che quando facevo la WaitForSingleObject e questa ritornava, oltre a chiudere l'handle del thread chiudevo anche il socket! Per questo motivo il suo valore veniva invalidato e di qui l'errore. Ora sembra non farlo più. :)

oregon
01-03-2010, 19:19
Certo ... questa può essere la causa ...

Loading