Verzeiflung nach FORK

oder auch: Send sucks!

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Verzeiflung nach FORK
Bin jetzt langsam am verzwiefeln:

	while(1){
		perror("1");
		send(sock, str, strlen(str) * sizeof(char), MSG_DONTWAIT);
		while( 0 < recv(sock, &buf,1,MSG_DONTWAIT)){
            perror("recv");
			printf("C:%c\n", buf);

		}
			if(EWOULDBLOCK != errno){
				perror("recv");
				printf("Verbindung beendet\n");
				close(sock);
				exit(1);
			}
		sleep(1);
	}

Wenn ich Zeile 2 auskommentiere dann werden die Zeilen 10 & 11 nicht mehr ausgegeben.

Habs auch schon mit setvbuf (stdout, NULL, _IONBF, 0) versucht, aber auch das mag nicht so recht.

Edit: PS: Der Frust steigt! Nicht mal das Aufräumen des Zombies hilft.


Ok habs! Man muss errno vorher auf 0 setzen. Sollte man wahrscheinlich immer machen…


warum genau checkst du auf EWOULDBLOCK

wenn dein recv blockiert und die whileschleife beendet wird dann kannste deinen socket eh schliessen und rausgehen


Boa! Hab langsam kein Bock mehr! Send terminirt wenn der Socket geschlossen wird! Das ist doch nicht logisch, oder?!? Habs auch nicht in der Doku gefunden! Es macht di funktion einfacher, weil man nichts mehr abfangen muss - und auch nicht kann. Naja Pluspunkt für all jene die sich über sowas kein Gedanken machen.


Wenn ein Socket geschlossen wird, dann wird dem Prozess ein SIGPIPE zugestellt. Die Standardreaktion darauf ist der sofortige Selbstmord des Prozesses, man kann das aber mit sigaction umstellen.

[edit: Huch nicht ganz richtig → siehe juk’s Beitrag weiter unten]


Ok, und was heißt das für uns? Sollen wir das Bewusst hinnehmen (Ich muss / kann eh keinen Fehler abfangen) oder sollen sigaction setzen oder sigaction nicht setzen und die Fehler trotzdem abfangen?


Da Signalbehandlung erst nächste Woche drankommt dürft ihr das bewusst hinnehmen :wink:


nee, lasst die Signale besser noch in Frieden -
kommt naechste Woche in den Uebungen (und da kommt dann auch eine schoene dicke
Aufgabe dazu).

btw. - was soll das Programm eigentlich machen???
Warum dieses nicht-blockierende senden und empfangen?
Mit dem timed hat das nix zu tun - oder etwa doch?


Beim Send hatte ich das nur Testweise drin. Und beim Empfangen muss es ja rein, sonst kann ich nicht senden. Habs eigentlich reingeschrieben, weil ich ein wenig blöd war und nicht geblickt hab, das sich der Prozess ja selber abschießt und mir send keinen Fehler ausgegeben hat.


der timed muss doch gar nichts empfangen?!


Ja schon, aber ich dachte das send nicht blickt, dass der Socket geschlossen wird( perror wurde nicht getriggert). Ist auch in den Manpages nicht so optimal beschriben.
Und immerhin kann ja send nach dem abschießen von Telnet noch einmal senden und recv noch einmal mit 0 zurückkehren, was mir ermöglicht hat sauber dicht zu machen. Erst beim nächsten aufruf von send wurde das Signal getriggert. :vogel:


Du bist nicht der Einzige, der gesucht hat warum seine Fehlerbehandlung für send nie ausgeführt wird …

Zum Glück hab’ ich den Thread hier gesehen, bevor ich mich noch weiter damit beschäftigen konnte.


mal abgesehen davon - warum macht ihr nicht einfach
fdopen auf den socket und dann printf oder fputs.
Oder einfach “write”.
send und recv braucht man in dem Fall eigentlich gar nicht.

Aber ich seh’ schon, dass wir da dieses Jahr in ein Problem reingelaufen sind
(bzw. Ihr), an das wir gar nicht gedacht haben.
Letztes Jahr hatten wir erst den Signalkram und dann den timed - und das
haben wir diesmal umgedreht. An den Abbruch durch SIGPIPE, wenn
die lesende Seite den socket zu macht, hab’ ich nicht mehr gedacht.

Also:
ein Prozess, der etwas in eine Pipe oder auf einen Socket schreibt, dessen
lesende Seite nicht mehr existiert, wird abgebrochen (es sei denn, er tut
was dagegen - und naechste Woche verraten wir, wie das geht).


Weil man sich am besten an die Aufgabenstellung hält. Sonst wird es einem nachher angekreidet, dass man’s nicht verwendet. Blos das Hirn nicht einschalten, dann ist der Lehrer unzufrieden, dass Du es nicht so gelöst hast wie er es wollte. So wurde es einem Jahrelang antreniert. (Und es wär ja nicht so, dass es an der Uni irgendwie besser wäre als in der Schule.)
Ach ja: Zumindest laut docu unterscheiden sich write und send bis auf die Flags, die ja 0 gesetzt werden nicht. Sonst hätt ich das ausprobiert.


Was soll denn diese diffuse Kritik, morty?
Wenn du einen konkreten Vorwurf bzgl. des Korrekturstils eines SOS-Übungsleiters hast, dann 'raus damit.
Andernfalls bitte piano mit deinen Allgemeinplätzen.


Ahhh Missverständnis! Das war in keinster Weise eine Kritik an SoS. Ich bin inzwischen im sechsten Semester Mechatronik und SoS gehört auf jeden Fall zu den Vorlesungen die deutlich über’m Schnitt liegen.
Nein, das war eine allgemine Kritik an unserem Bildungssystem und der Einstellung eines Großteils der lehrenden Schicht. Es war eine ernst gemeinte Antwort auf juk’s Frage.
Wenn ich jemanden angreifen will, dann mach ich das schhon direk. :wink:
Sorry, falls es falsch rüber gekommen ist.


Ich denke dass du hier noch keine ordentlichen Antwort bekommen hast liegt daran, dass die meisten (mich eingeschlossen) das Problem nicht ganz verstehen. Z.B. kann ich das obige Codestück dem timed nicht wirklich zuordnen… Mit Zombies aufräumen hat Dein Problem nichts zu tun, die ändern am Verhalten Deines Prozesses nichts wenn sie einfach nur rumgeistern.

Die Schleife im Sohnprozess stelle ich mir etwa so vor:

char time[20];

while(1) {
  current_time(time, 20);
  write(socket, time, strlen(time));
  sleep(1);  
}

Das ganze mit entsprechender Fehlerbehandlung sollte funktionieren. Wenn der client irgendwann die Verbindung dicht macht wird das Kind einfach sterben womit die Sache für Dich erledigt ist. Es hängt dann zwar als Zombie weiter im System solange Dein timed läuft aber das braucht Dich bei der Programmmierung nicht weiter zu stören, es beeinflusst nicht das Verhalten Deines timed oder das von weiteren Kindern die für andere Verbindungen erzeugt werden.
btw ist der im write verwendete socket natürlich der socket, der vom accept im Vater zurückgeliefert wurde, nicht der socket der als Parameter von bind/listen/accept verwendet wurde — nur um Missverständnisse hier auszuräumen…


Eigentlich haben sich für mich alle Fragen gelöst. Habs nur ein wenig koplizierter gemacht als nötig, weil nicht kapiert hab das sich der Prozess selbst erschießt.


[quote=juk]mal abgesehen davon - warum macht ihr nicht einfach
fdopen auf den socket und dann printf oder fputs.
Oder einfach “write”.
send und recv braucht man in dem Fall eigentlich gar nicht.[/quote]

Na ja, ich dachte eben send ist schöner, da ein write auf einen Socket ja nur unter Unix funktioniert. Und da bei den anderen Aufgaben ja ziemlich viel Wert auf Portierbarkeit gelegt wurde wollt’ ich’s eben besonders vornehm machen. :wink:

Aber gut, unter Windows funktioniert ein normales close für einen Socket auch nicht und dann ist es eigentlich schon egal, ob man noch ein paar Anweisungen mehr oder weniger erstzt.