/*******************************************************************************/ /* _________________________________________ */ /* / WARNUNG: Das hier ist keine Vorlage, \ */ /* | oder ein vorbildliches, robustes | */ /* | Programm. Es fehlt jegliche | */ /* | Fehlerbehandlung, und könnten | */ /* | Leichtsinnsfehler enthalten sein, weil | */ /* | es sich genau um den Stand aus der | */ /* | Tafelübung handelt. Die Absicht ist es | */ /* | die Möglichkeit anzubieten, weiter an | */ /* | dem erarbeiteten Programm aus der Übung | */ /* | spielen zu können, ohne alles wieder | */ /* | von vorne schreiben zu müssen. Bitte | */ /* | kopiert also nichts aus dieser Datei in | */ /* \ euren Abgaben. / */ /* ----------------------------------------- */ /* \ / \ //\ */ /* \ |\___/| / \// \\ */ /* /0 0 \__ / // | \ \ */ /* / / \/_/ // | \ \ */ /* @_^_@'/ \/_ // | \ \ */ /* //_^_/ \/_ // | \ \ */ /* ( //) | \/// | \ \ */ /* ( / /) _|_ / ) // | \ _\ */ /* ( // /) '/,_ _ _/ ( ; -. | _ _\.-~ .-~~~^-. */ /* (( / / )) ,-{ _ `-.|.-~-. .~ `. */ /* (( // / )) '/\ / ~-. _ .-~ .-~^-. \ */ /* (( /// )) `. { } / \ \ */ /* (( / )) .----~-.\ \-' .~ \ `. \^-. */ /* ///.----..> \ _ -~ `. ^-` ^-_ */ /* ///-._ _ _ _ _ _ _}^ - - - - ~ ~-- ,.-~ */ /* /.-~ */ /*******************************************************************************/ #include #include #include #include #include #define SIGNAL_TO_USE SIGUSR1 /* Kindprozess: Versucht zu leben */ static int lives = 100000; static void sig_handler(int sig) { /* achte auf signal-safety(7)! */ (void) sig; if (lives > 0) lives--; } static sigset_t critical, initial; static void try_to_live(void) { sigprocmask(SIG_BLOCK, &critical, &initial); /* FEHLERBEHANDLUNG! */ while (lives != 0) { printf("lives: %d\n", lives); #ifdef NO_SIGSUSPEND sigprocmask(SIG_SETMASK, &initial, NULL); /* FEHLERBEHANDLUNG! */ pause(); sigprocmask(SIG_BLOCK, &critical, &initial); /* FEHLERBEHANDLUNG! */ #else sigsuspend(&initial); #endif } sigprocmask(SIG_SETMASK, &initial, NULL); } /* Elternprozess: Versucht zu töten */ static void try_to_kill(pid_t pid) { while (0 == waitpid(pid, NULL, WNOHANG)) { /* TODO: FEHLERBEHANDLUNG! */ kill(pid, SIGNAL_TO_USE); /* TODO: FEHLERBEHANDLUNG! */ } } int main() { /* Installiere ein Signal-Handler für SIGNAL_TO_USE */ struct sigaction act = { .sa_handler = sig_handler, .sa_flags = SA_RESTART, }; sigemptyset(&act.sa_mask); sigaction(SIGNAL_TO_USE, &act, NULL); /* TODO: FEHLERBEHANDLUNG! */ /* Starte ein Prozess mit `lives' vielen Leben, und eines welches * den ersten umbringen will. */ sigemptyset(&critical); /* FEHLERBEHANDLUNG! */ sigaddset(&critical, SIGNAL_TO_USE); /* FEHLERBEHANDLUNG! */ pid_t pid = fork(); if (pid == -1) { /* Fehler */ perror("fork"); return EXIT_FAILURE; } else if (pid == 0) { /* Kind */ try_to_live(); /* kill(getppid(), SIGKILL); */ } else { /* Eltern */ try_to_kill(pid); } return EXIT_SUCCESS; }