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.
Aufgabe 2 - rush
Morgen,
[s]Gibt es die “standard” Reihenfolge für inFile und outFile, d.h. “ [] [<inFile] [>outFile]”, oder können die Token überall stehen und uns das Leben schwer machen?
Bzw. was tut man wenn jemand etwas “blödes” macht wie “>outFile <inFile ls -al”? Ich sehe da mit String-Token-Ansatz keine wirkliche Lösung? Da ich die Eingabe ja nicht in Teilstrings zerlegen kann, weil ich nie weiß wie viele es gibt…
Am Ende sollte man ja den command + evtl. paramter weitergeben können und evtl. übergebene in- und outFile zur umleitung extrahiert haben, aber mir fällt da gerade keine saubere Lösung ein wenn ich mich nicht auf eine feste Form verlassen kann, und ich wüsste auch nicht, was man tut wenn jemand sich nicht an diese Form hält…[/s]
Man könnte auch mal einfach alle *.h Files vorher lesen, und sehen, dass das schon alles für einen gemacht wird…
in Teilaufgabe d) steht, dass “das Warten auf Vordergrundprozesse nun mittels sigsuspend(2) erfolgen muss”.
Mometan verwende ich noch den Originalcode mit waitpid und hatte bisher keine Probleme.
Ich könnte mir allerdings vorstellen, dass diese Konstellation zu einem Deadlock führen könnte, wenn der SIGCHLD Handler ausgeführt wird, bevor waitpid zurückkehrt. Dort wird dann wiederum waitpid aufgerufen und der Zombieprozess entsorgt. Das waitpid (mit der PID des schon aufgeräumten Vordergrundprozesses) wird dann neugestartet (SA_RESTART) und wird nie mehr zurückkehren.
(Kehrt waitpid zuerst zurück, sollte es weiter keine Probleme geben. Der Handler kehrt dann einfach zurück, ohne einen Kindprozess mit verändertem Zustand gefunden zu haben.)
In der Manpage von waitpid(2) wird jedenfalls erwähnt, dass es von einem signalhandler unterbrochen werden kann, aber nicht spezifiziert, ob es bei SIGCHLD garantiert zuerst zurückkehrt, oder der Handler ausgeführt wird, weswegen ich mal annehme, dass wirklich beide Fälle eintreten können und das der Hintergrund für diesen Teil der Aufgabenstellung ist.
Kommentare?
Interessehalber: Gibt es eine Möglichkeit, CTRL-Z so zu behandeln, dass statt der rush, nur der laufende Vordergrundprozess das SIGSTOP zugestellt bekommt?
Wird das in den shellutils gehandled oder liegt der entsprechende Mechanismus eine/mehrere Ebene/n tiefer (bash, Terminalemulator … ) ?
Gut erkannt, genau das ist das Problem an dieser Stelle.
[quote=etXzat]In der Manpage von waitpid(2) wird jedenfalls erwähnt, dass es von einem signalhandler unterbrochen werden kann, aber nicht spezifiziert, ob es bei SIGCHLD garantiert zuerst zurückkehrt, oder der Handler ausgeführt wird, weswegen ich mal annehme, dass wirklich beide Fälle eintreten können und das der Hintergrund für diesen Teil der Aufgabenstellung ist.[/quote]Ich glaube es wird immer erst der Signalhandler ausgeführt – wenn die Manpage sich dazu ausschweigt ist es aber gut möglich, dass nicht spezifiziert ist, wie sich das System zu verhalten hat. In diesem Fall hilft es dir nichts, wenn dein Code auf Linux funktioniert, auf FreeBSD oder OS X das Verhalten aber anders implementiert ist… zu solchen Unterschieden hilfreich sind auch (falls verfügbar) die Manpages aus der [m]3p[/m]-Sektion, in diesem Fall also [m]man 3p waitpid[/m].
[quote=etXzat]Interessehalber: Gibt es eine Möglichkeit, CTRL-Z so zu behandeln, dass statt der rush, nur der laufende Vordergrundprozess das SIGSTOP zugestellt bekommt?
Wird das in den shellutils gehandled oder liegt der entsprechende Mechanismus eine/mehrere Ebene/n tiefer (bash, Terminalemulator … ) ?[/quote]
Das sollte möglich sein, indem du in der rush und in allen gestarteten Hintergrundprozessen die Signalbehandlung von SIGSTOP auf ignorieren setzt. Die Behandlung von SIGSTOP ist Teil des Feature-Sets von Shells (also z.B. bash, zsh, …). Nachdem die rush eine Shell ist, wäre das die richtige Stelle, um dieses Verhalten zu implementieren. Solange du kein [m]fg[/m]-Kommando zum Fortsetzen implementierst ist das allerdings relativ nutzlos…
Die Lösung mit [m]SIGSTOP[/m] ignorieren funktioniert jedoch nicht richtig, wenn Programme selbst ihre Signalbehandlung ändern. Die richtige Lösung, die auch echte Shells verwenden, sind Prozessgruppen ([m]setpgid(3)[/m], [m]tcsetgrp(3)[/m]). Es gibt jeweils eine Prozessgruppe die im Vordergrund ist, und nur dieser stellt das Terminal (das hat mit der Shell nichts zu tun!) Signale zu. Aber für SP2 wäre das zu viel Aufwand, weswegen man das dort nicht so macht.
Das Management der Prozessgruppen wäre dann aber wieder Aufgabe der Shell, weil nur die weiß welcher Prozess gerade der Vordergrundprozess ist, oder verstehe ich das falsch? Die Zustellung des Signals passiert dann durch das Terminal, aber eben nur die Zustellung, nicht die Gruppierung in die Gruppen.
Genau. (Mir ging es um die Zustellung, das macht das Terminal. Wer gerade Vordergrund-/Hintergrundprozess ist, das merkt sich die Shell und teilt es dem Terminal mit, was dann entsprechend auftretende Signale zustellt - nämlich an die Vordergrund-Prozessgruppe.)
Danke @neverpanic, @rudis
Ein paar Erkenntnisse zur Vollständigkeit:
Laut signal(7) kann man SIGSTOP eh nicht ignorieren (wie SIGKILL).
Danke für den Hinweis mit den Prozessgruppen. In meine rush wird es dieses Feature aber wohl nicht mehr schaffen.
Alternativ bin ich auf einen Ansatz gekommen, der mit tcsetattr (termios(3)) das Terminal so umkonfiguriert, dass bei CTRL-Z kein SIGSTOP gesendet wird. Liest die shell nun das entsprechende Zeichen ein, kann sie SIGSTOP an die entsprechenden Prozesse senden. Damit hätte man die Signalzustellung in die Shell ausgelagert. Sinnvoller ist wohl rudis’ Lösung.
Stimmt. Deswegen wird normalerweise auch [m]SIGTSTP[/m] vom Terminal zugestellt (und kein [m]SIGSTOP[/m]), da hab ich nicht aufgepasst.