Aufgabe 6


Signal: Pipe

This signal is raised when a program writes to a socket or fifo that has no readers. The default action of this signal is to cause the program to terminate.

You might see this message if you have a series of commands in a shell pipe line and one of the processes quits. Eg:

$ cat somefile | head

After “head” has printed out the first 10 lines and quits, “cat” will get a pipe error. However, cat catches the signal and quits gracefully. If you pipe the output of some cvs(1) commands into less(1) and quit, then you might see the shell print out a message as cvs doesn’t handle this signal gracefully.

// google suche nach “sigpipe”, 2. ergebnis

falls dir die erklärung aber nichts hilft, kann ichs gerne noch mal mit eigenen worten versuchen :slight_smile:


sowas hab ich schon auch gelesen, ich weiss nur nicht wie ich das anwenden soll? Heisst dass, ich muss einfach das write()machen, und wenn “-1” zurückkommt kam das SigPipe Signal (oder es gab einen Fehler)?
Oder muss ich das Sigpipe Signal irgendwie speziell abfangen (hab die trshell noch nicht, da kommen doch auch Signale vor, muss ich die schon kennen dazu?)


wenn du gar nichts machst killt das sigpipe dir das kind das ist zwar nicht grade sauber sollte aber funktionieren…


timed.c: In function `main':
timed.c:30: warning: implicit declaration of function `write'
timed.c:39: warning: implicit declaration of function `close'

… hab ich falsche flags für den gcc gesetzt oder woher kommt das ??? bzw. was ist das :smiley:


header unistd.h vergessen?


uuuuuuups :wand:
danke !!! :smiley:


Okay, dann ist mein Dämon fertig :smiley:


noch ein (hoffentlich) letztes mal zu sigpipe. mein bisheriger code:

while (write (othersocketchild [...]) != -1) {
                                [...]
                        }
                        close (othersocketchild);
                        exit (EXIT_SUCCESS);

heisst das also, dass meine letzten beiden zeilen nicht noetig sind, er bei einem sigpipe also schon vorher terminiert und gar nicht soweit kommt? dann waere es immerhin noch sinnvoll, fehlerabfrage zu machen, weil write () ja auch wegen anderen sachen -1 returnen kann…


noch eine frage:
soll man den port, den man benutzen soll irgendwie ueber den output von /usr/bin/id ermittelt oder einfach per #define an den anfang machen?


sodala, letzte frage fuer heute:
langt ein

listen (mysocket, 1)

eigentlich, also eine 1-elementige queue, wenn danach sowieso sofort geforkt wird? oder soll man zur sicherheit 5 connections in die queue lassen?


  1. mach zur Sicherheit doch lieber 5 Connections :wink:
  2. ist egal ob du den hardcodest oder getuid() aufrufst
  3. Fehlerabfrage für write auf jeden Fall. Schöner wäre es auch wenn du das SIGPIPE abfängst, zB SIG_IGN und danach errno auf EPIPE prüfst, dann terminiert dein Programm auch gescheit.

Arghh, was heisst dass denn jetzt schon wieder. Kannst du das vielleicht noch ein bisschen in Kot umformulieren, vielleicht check ichs dann besser?
Im Moment siehts so bei mir aus

if(write()<0){
perror(„writeerror“)
free(socket)
exit(-1)
}

Wie mach ich das, was du da oben schreibst?


das was du geschrieben hast is nur die fehlerabfrage, passt auch wenn du dir den prozess von sigpipe killen lässt.

wenn du für sigpipe mit sigaction das signal ignorierst (SIG_IGN) (>manpage) wirft dein write auch einen fehler, und du kannst prüfen ob errno==EPIPE dann weisst du nämlich dass die pipe geschlossen wurde und kein sonstiger fehjler aufgetreten ist


vielen dank,
die 3 punkte sind integriert
und ich glaube, ich schliesse damit den daemon ab…


Mein timed läuft schon ganz gut.

Ich habe jedoch eine kleine Bbesonderheit bei der Behandlung von accept:

Wenn mir ein Client durch eine unterbrochene Terminalverbindung abgurkt (SIGPIPE wird mit SIG_IGN behandelt), läuft das accept mit einem EINTR schief. Vermutlich ein SIGCHLD während dem accept. Soweit so gut.

Mit kreativem Einsatz von if und errno macht das Programm auch so in etwa was es soll.

Tritt bei euch auch ein EINTR auf?


Vielleicht nochmal zur Erklaerung, warum es sinnvoll (aber nicht unbedingt notwendig) ist, das SIGPIPE abzufangen und dann mit exit(EXIT_SUCCESS); zu beenden:
Der Prozess, der diesen beendeten Prozess dann mit waitpid/wait abfaengt bekommt so ueber den Rueckgabewert die Information, dass dieser ordnungsgemaess beendet wurde. Wenn SIGPIPE direkt beendet wuerde da ein Fehlerstatus drinstehen.

Die Sache mit dem unterbrochenen accept ist ganz normal und deshalb muss accept auch neu gestartet werden, wenn accept fehlschlaegt und die errno danach gleich EINTR ist. Unterbrochen wird das durch das SIGCHLD, in dessen Signalhandler ja die terminierten Sohnprozesse aufgesammelt werden sollen.

" free(socket)" ist nicht so ganz richtig, du willst (vermutlich) den socket, also einen filedescriptor schliesen, das geht mit close(socket); . free darf nur auf Pointer angewandt werden, die malloc, realloc oder calloc mal zurueckgeliefert haben.


Man dankt für die Antwort. Ich dachte schon, ich wäre der einzige, dem das passiert :wink:


Aus ‚ps‘:

Scheinbar nicht. Hätte ich aber auch gerne! Nur leider steht auch in der accept-manpage nix von einem EINTR oder dieser Erscheinung drin. Kann mir jemand verraten, wie man sowas anstellt? Ansonsten werden meine Childprozesse jetzt eben so lange aufgehoben, bis der timed beendet wird.

Update: es bleibt immer nur ein Prozess übrig. Alle anderen werden entfernt, soweit vorhanden. Aber erst, wenn eine neue Verbindung aufgebaut wird…


errno wird auf EINTR gesetzt, wenn ein signal während accept komt (unter anderem).

Entspricht defunct einem Zombie?


Dafür müsste accept aber auch unterbrochen werden, oder? Und wenn bei mir accept unterbricht ohne ein Socket zu liefern, ist es aus! Da mein timed aber munter weiterläuft, kann bei mir kein EINTR auftreten.

Denke schon… wüsste jedenfalls nicht, was es sonst sein soll.