Hmm ich habe ein kleines Problem mit send() und lokalen Unix socket(SOCK_STREAM) als IPC zwischen einigen threads. Offenbar wird nach dem send() der buffer Inhalt nicht sofort oder gar nicht in den Kernel Buffer geschrieben, so das nur noch Käse ankommt wenn man send() zu schnell hintereinander im selben Thread aufruft. Normalerweise blockiert es ja wenn der Inhalt nicht in den Buffer passt, es kopiert die Daten in den Kernel buffer und gibt die geschrieben bytes zurück. Das kopieren in das socketFile erfolgt anscheint nicht sofort durch den Kernel wenn man das so nennen darf? Schickt man den thread dazwischen schlafen funktioniert es.... Keine Lösung, ich kann nicht wissen wann der Kernel fertig ist. select() hilft auch nicht da der descriptor wieder zum schreiben bereit ist, rauscht das ganze genau so wieder durch. Ich müsste mein Result komplett zwischen buffern und dann senden. Ich wollte es in kleinen teilen senden. Beim Server werden die Client Sockets gemultiplext per select(). Das wird doch nicht die Ursache sein ?
:
Bearbeitet durch User
Ohne code kann man nichts sagen. Du hast sicher irgendwo eine race condition oder sonst einen fehler. Behandelst du den EINTR fehler fall? Das Problem liegt aber definitiv nicht bei send oder dem kernel (ausser vielleicht falls du das WSL verwendest).
Hast du evtl den socket auf non-blocking gesetzt? Was sagt der Return-Wert von send?
Der Return Wert sind die gesendeten Bytes, kein Error. Das Problem ist ja nicht das blockieren, das geschieht ja nur wenn der Kernel Buffer voll ist. Sondern das der Inhalt des Datenbuffers zwischen den send() aufrufen verändert wird. Ich ging aber davon aus das die Daten schon vom Kernel geschrieben wurden, sobald send() zurück kehrt. Send() ist nicht thread sicher, hmm ich schau nach. Der Socket,Buffer usw. wird nur von einem thread verwendet...
:
Bearbeitet durch User
Du könntest noch schauen, ob du mit "strace -f" etwas siehst. Bei Raceconditions kann es aber vorkommen, das der Fehler, den man Debuggen will, durch das geänderte Timing verschwindet.
Marco H. schrieb: > müsste mein Result komplett zwischen buffern und dann senden. Ich > wollte es in kleinen teilen senden. Zeige uns den Code! Ich kann mir sehr gut vorstellen das Du eine Race Condition in Deinem Code übersehen hast. Linux Kernel Zeuchs ist relativ gut ausgetestet.
Irgendwie hab ich den Eindruck, das du nicht send(2), den direkten Kernelcall, sondern irgendeine buffered Variante benutzt.
Den Eindruck habe ich auch... Ich bin auch der Meinung das es an meinen Code liegt ;). Ich habe er einen anderen verdacht... das hängt mit select() zusammen. Dann wenn die Situation auftritt landen daten master_socket, accept läuft durch und gibt einen weiteren fd zurück... Da ist was faul.... das passiert eben immer dann wenn das Problem auftritt, außer wenn man zwischen den senden den thread kurz schlafen legt.
also wenn man es in 1k blöcken sendet funktioniert es... sobald man mehr sendet läuft etwas über und es kommt zu Fehlfunktionen. Nun gut sende ich eben alles in 1k blöcken. Aber ich dachte das wäre beim localen socket egal, send blockiert komischer weise auch nicht..
tada... jetzt funktioniert es. Die Ursache lag am fastcgi Modul, genauer gesagt in der read Funktion. Die Berechnung wie viele values übertragen werden war fehlerhaft :(. Wenn man die Pakete nicht ausließt blockiert send() wie es soll, bis eben wieder etwas ausgelesen wird. Zum Projekt.... Es wird ein AVB Controller der über HTTP/Rest.. Was man sieht ist die Antwort als Json und stellt die Geräte mit ihrer ID dar. 3000 Geräte gibt es natürlich nicht ;) durch die MAC Adressen durch das MAAP ist das auf 256 Geräte begrenzt. Der token dient später dazu auch kleineren Geräten mit begrenzten Buffer den controller zu nutzen. Per query übergibt man einfach maxResults und bekommt einen token zurück. Der AVDECC Stack kann schon einiges ;), ich muss jetzt aber erstmal die Rest API hinbekommen um weiteres zu implementieren zu können. Ich habe jetzt 30 fastCGI child Prozesse offen in dem auch das Json gebaut wird. Ist es besser Connect -> Daten Transfer -> Close ? oder offen lassen. Wenn ich den Socket immer wieder schließe bekomme ich im fastcgi Modul mit wenn der Server nicht läuft. Das Modul schläft ja und versucht dann was zu senden. Durch das load Balance macht das dann jedes der 30 childs und scheitert zuerst einmal.
Beitrag #5460603 wurde vom Autor gelöscht.
DPA schrieb: > Du könntest noch schauen, ob du mit "strace -f" etwas siehst. Bei > Raceconditions kann es aber vorkommen, das der Fehler, den man Debuggen > will, durch das geänderte Timing verschwindet. strace(1) und ltrace(1) haben leider dasselbe Timing-Problem.
Marco H. schrieb: > Den Eindruck habe ich auch... Ich bin auch der Meinung das es an meinen > Code liegt ;). Ich habe er einen anderen verdacht... das hängt mit > select() zusammen. Dann wenn die Situation auftritt landen daten > master_socket, accept läuft durch und gibt einen weiteren fd zurück... select(2), poll(2) und epoll(7) werden vielfach benutzt und sind daher sehr gut ausgetestet. Es wäre sehr ungewöhnlich, wenn Du ausgerechnet dort einem Fehler aufgesessen wärest. > Da ist was faul.... das passiert eben immer dann wenn das Problem > auftritt, außer wenn man zwischen den senden den thread kurz schlafen > legt. Dann mach' doch bitte mal ein Minimalbeispiel, das den Code reproduziert, und poste das hier. n Augen sehen ja meistens mehr als zwei.
Es funktioniert, der Read im Client war nicht gut gelöst. Das Problem ist das ich beim erzeugen des Json nachladen muss. Das Paket wird an mehreren Stellen je nach Buffer gebrochen und muss dann wieder zusammen geklebt werden. Da kann schon mal was in die Hose gehen... Ich hatte mehrere Fehler drinnen. 1. Das Pakete im Socket Buffer blieben. 2. Das diese falsch zusammen geklebt wurden.
So ich habe das mal extrahiert... Ich baue die Verbindung erst auf nach einen http Request auf und wenn keine traffic über das Modul läuft wird der socket geschlossen per messages "CLOSE" an den Server. Beim starten wird jetzt nicht mehr sofort eine Verbindung auf gebaut. Das umgeht das Problem wenn sich der Controller beendet und das fastCGI Modul davon nichts mitbekommt da es ja schläft. Erst beim Request merkt das betroffen Modul das die Verbindung fehlt. Das hatte den blöden Randeffekt das 30 Module erst mal an getriggert werden mussten. Per Zufall welches das Load balancing gerade ansprach. Daten -> Fehler -> Fehler -> Daten Auf der Server Seite werde ich was ähnliches bauen, die letzte Aktivität überwachen und wenn auf dem socket nach x nichts los war muss dieser korrupt sein und er wird geschlossen. Das passiert nur wenn sich das fastcgi Modul bzw. der Webserver unschön beendet. Das Signal SIGTERM fange ich ja ab und schließe den Socket ordentlich. Das lesen ist übrigens wichtig beim Einsatz von select, dadurch wird der FD zurückgesetzt. Ohne lesen des Sockets entsteht eine schleife... Die Funktion wird in einer schleife aus geführt...
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.