Socket select mit unerklärlichen Absturz...
-
Bilder sprechen mehr als tausend worte, daher mal ein Link wo er abkackt.
http://virtualdreamsdd.dyndns.org/debug.png
Im Release Modus stürzte er jetzt komischweise grad mal nicht ab.Hab Debugausgaben, nur beim Server kann man sie nicht mehr lesen so schnell ist er weg, bzw hängt es nicht an der Funktion, sondern an etwas anderem wie man auf dem Bild sehen kann. Hab im DOS Fenster ausgaben zum WSAGetLastError() und MessagesBoxen für da wo er grad ist, die kommen aber nie, also kackt er vorher ab.
-
VirtualDreams schrieb:
Wenn die Funktion mit 0 zurückkehr wird ein neuer Thread gestartet der den neuen Client mit accept annimmt und komplett im Thread bearbeitet.
Wieviele Threads werden im Debug-Fenster unten links angezeigt in dem Augenblick wo die Exception ausgelöst wird ?
-
2 stück:
3520 __tmainCRTStartup std::_Lockit::~_Lockit Normal 0 > 2476 __tmainCRTStartup _unlock Normal 0
-
VirtualDreams schrieb:
2 stück
Das bedeutet ja, dass ein Client "angebissen" hat, der Server ein Thread erzeugt und daraufhin abstürzt.
Kannst Du mal die "ClientProc" von "CreateThread(NULL, NULL, ClientProc, this, NULL, NULL)" posten ?
-
Jup, anbeisen tut er ^^ Aber hier der gewünschte code:
int SmartSockServer::Run() { SOCKINFO client; char buffer[256]; char text[256]; int res; int bytes; int number; if((res = socket_accept(server, client))) return res; else { LeaveCriticalSection(&crit); socket_recv(client, buffer, 256, bytes); buffer[bytes] = '\0'; sscanf_s(buffer, "%i %s", &number, text); if(number == 100) { if(strstr(text, "admin") == 0) { MessageBox(NULL, "USER OK", "Debug", NULL); sprintf_s(buffer, 256, "%i", 110); socket_send(client, buffer, 256, (int)strlen(buffer)); socket_recv(client, buffer, 256, bytes); buffer[bytes] = '\0'; sscanf_s(buffer, "%i %s", &number, text); if(number == 130) { if(strstr(text, "admin") == 0) { sprintf_s(buffer, 256, "%i", 140); socket_send(client, buffer, 256, (int)strlen(buffer)); MessageBox(NULL, "PASS OK", "Debug", NULL); } else { sprintf_s(buffer, 256, "%i", 150); socket_send(client, buffer, 256, (int)strlen(buffer)); socket_close(client); MessageBox(NULL, text, "PASS NOT OK", NULL); return 0; } } } else { sprintf_s(buffer, 256, "%i", 120); socket_send(client, buffer, 256, (int)strlen(buffer)); socket_close(client); MessageBox(NULL, text, "USER NOT OK", NULL); return 0; } } } MessageBox(NULL, "We leave te thread", "Debug", NULL); return 0; } DWORD WINAPI ClientProc(LPVOID param) { SmartSockServer *server = (SmartSockServer*)param; if(server) server->Run(); return 0; }
-
entweder ich bin blind oder du hast das select schon irgendwie rausgenommen, weil ich kann nirgends den aufruf von socket_select entdecken, btw. in deinen vorherigen posts .... desweiteren ist mir ne kleinigkeit bei deinem socket_accept aufgefallen,
if(INVALID_SOCKET == (new_sockinfo.socket = accept(sockinfo.socket, (SOCKADDR*)&new_sockinfo.addr, &new_sockinfo.addr_size))) { return WSAGetLastError(); }mach doch mal testhalber 2 zeilen draus
new_sockinfo.socket = accept(sockinfo.socket, (SOCKADDR*)&new_sockinfo.addr, &new_sockinfo.addr_size); if(INVALID_SOCKET == new_sockinfo.socket) { return WSAGetLastError(); }denn WENN rein zufällig
INVALID_SOCKET == true auch true ergibt könnte eventuell dein programm bei
if((res = socket_accept(server, client))) return res; elseaussteigen weil WSAGetLastError() 0 zurückgibt wenn es keinen fehler gibt.
kleinen moment ....
(res = socket_accept(server, client)) ist immer true !!!
dein programm dürfte theoretisch gar nciht über das return res in deiner run() hinwegkommenoder hab ich grad alles verpeilt ??
... oder wars INVALID_SOCKET ?? mist leider kann man beim AW schreiben die seiten nicht blättern um code zu kopieren
-
ok, ich probier das mal aus, ich mach mal 2 zeilem draus.
Hier noch mal die vergessene Funktion von vorhin:int SmartSockServer::Accept() { if(!socket_isvalid(server)) { while(!socket_isvalid(server)) { if(!socket_select(server)) { EnterCriticalSection(&crit); CreateThread(NULL, NULL, ClientProc, this, NULL, NULL); MessageBox(NULL, "New thread", "Debug", NULL); } } } MessageBox(NULL, "OK, we lost the server", "Debug", NULL); return 1; }
-
Hab es mal auf 2 Zeilen gemacht, das problem besteht trotzdem an der selben stelle.
if((res = socket_accept(server, client))) return res; else { LeaveCriticalSection(&crit); socket_recv(client, buffer, 256, bytes); buffer[bytes] = '\0'; sscanf_s(buffer, "%i %s", &number, text); //hier oder if(number == 100) //hier hauts den karren an die wand, da steigt er aus wie es oben auf dem bild zu sehen ist
-
Probier mal ob Du die "ClientProc" aufrufen kannst ohne dass der Server dabei abstürzt :
// CreateThread(NULL, NULL, ClientProc, this, NULL, NULL); ClientProc (this);
-
Er stirbt mit der selben Accessviolation (0xfdfdfdfd)
if(!socket_select(server)) { //EnterCriticalSection(&crit); //CreateThread(NULL, NULL, ClientProc, this, NULL, NULL); ClientProc(this); MessageBox(NULL, "New thread", "Debug", NULL); }in dem Bereich. Er kann auserdem nichts mehr an Sourcecode aufrufen, nur Disassembly
-
Stürzt der Server auch ab wenn in der "ClientProc" "nichts" drinsteht :
DWORD WINAPI ClientProc(LPVOID param) { return 0; }Falls nicht, dann das gleiche nochmal mit :
DWORD WINAPI ClientProc(LPVOID param) { SmartSockServer *server = new (SmartSockServer); delete (server); return 0; }
-
Mit beiden Methoden probiert und stürzt nicht ab, da der Client aber nicht angenommen wird kommt immer wieder die anfrage rein
-
Gibt wohl ein Problem mit der Threaderzeugung. Probier jetzt so :
... if(!socket_select(server)) { EnterCriticalSection(&crit); CreateThread(NULL, NULL, ClientProc, this, NULL, NULL); // ClientProc(this); MessageBox(NULL, "New thread", "Debug", NULL); } ... DWORD WINAPI ClientProc(LPVOID param) { // erstmal "leer" return 0; }Wenns läuft, dann so :
... DWORD WINAPI ClientProc(LPVOID param) { SmartSockServer *server = (SmartSockServer*)param; if(server) server -> Run (); return 0; } ... int SmartSockServer::Run() { // erstmal "leer" MessageBox(NULL, "We leave te thread", "Debug", NULL); return 0; }
-
OK, das geht auch einwandfrei
-
Sehr gut, nun schrittweise weiter :
int SmartSockServer::Run() { SOCKINFO client; char buffer[256]; char text[256]; int res; int bytes; int number; if((res = socket_accept(server, client))) return res; else { // hier "leer" } MessageBox(NULL, "We leave te thread", "Debug", NULL); return 0; }Wenns läuft dann :
... else { LeaveCriticalSection(&crit); } ...
-
OK, auch das funktioniert einwandfrei.
Hab langsam das gefühl das eine string funktion nicht threadsafe ist, oder vlt doch was anderes?
Bin jetzt selbst soweit gekommen:
int SmartSockServer::Run() { SOCKINFO client; char buffer[256]; char text[256]; int res; int bytes; int number; if((res = socket_accept(server, client))) return res; else { LeaveCriticalSection(&crit); socket_recv(client, buffer, 256, bytes); buffer[bytes] = '\0'; //sscanf_s(buffer, "%i %s", &number, text); //<--- ab der schmiert er ab im Debugbuild!!!
-
Hab mal ein wenig nachgelesen:
char buffer[256]; char text[256]; sscanf_s(buffer, "%i %s", &number, text, sizeof(text)); // <-- sizeof fehlteund jetzt stürzt er vorerst nicht mehr ab ^^. Das sizeof() hab ich aber bisher noch nie wo gesehen... O_o
-
Dann hat also sscanf_s () über die Grösse von "text" hinausgelesen und dadurch die Exception ausgelöst.
Verhindern lässt sich das durch sizeof () als letzten Parameter ?
Aha.
Prüfe unbedingt mal ob sprintf_s () auch solche Überraschungen bereithält.

-
sprintf_s hat nicht solche überraschungen, zumindstens konnte ich keine entdecken, der sizeof() parameter ist erst mit der secure version von sscanf_s hinzugekommen, ohne Threads und ohne sizeof() gabs irgendwie nie solche exceptions ^^.
-
Euch ist schon klar dass eine CRITICAL_SECTION "owned" ist, also nur von dem Thread aus verlassen (leave) werden darf der sie auch betreten hat (enter)?
Wenn ja, dann möge mir mal einer erklären was hier abgeht, dann verstehe ich das ganze nicht.
Wenn nein, dann dürfte wohl genau das das Problem sein.
EDIT:
Hab langsam das gefühl das eine string funktion nicht threadsafe ist, oder vlt doch was anderes?
Natürlich sind string Funktionen nicht threadsafe.
Die einzigen 2 Dinge die "threadsafe" sind sind 1) Operationen in unterschiedlichen Threads auf unterschiedlichen Strings und 2) ausschliesslich Leseoperationen in unterschiedlichen Threads auf dem selben String.
Zumindest sind das die Regeln was wahrscheinlich 99% aller Implementierungen der STL bzw. der C-Style String Funktionen angeht (strcpy, strcat, strlen etc.).EDIT2: weiters frage ich mich wie wohl socket_recv aussieht -- das riecht auch nach Problemen. Solange die Länge des "Paketes" nicht mitgeschickt wird kann socket_recv nämlich nicht wissen wieviel Bytes ankommen sollen - und wird dann hin und wieder nur einen zu kurzen String empfangen.
EDIT3: sscanf ist eines der grauseligsten Untiere der C-Lib, würde ich niemals verwenden.