sys_call beendet sich nicht Multi-Threading - Prozess-Management



  • Hallo Leute,

    ich habe ein Problem mit meinem Prozess-Management. Ich habe eine Multi-Threading Anwendung, welche innerhalb eines Thread einen Child-Prozess erstellt, welcher einen sys_call fährt. Das Problem ist, das der sys_call nur ein bestimmtes Zeitfenster hat, danach muss dieser sterben, egal ob er fertig ist oder nicht.

    Wenn ich den Child-Prozess abschieße (mit SIGTERM ) wird der sys_call an den init Prozess gehangen, was irgendwie überhaupt nicht mein Ziel ist, er soll doch einfach nur sterben.

    Ich habe mal ein reproduzierbares Beispiel geschrieben. Der sys_call ruft eine Bash-Datei auf, welche nur eine Sleep-Anweisung beinhaltet, um das ganze zu testen.

    #!/bin/bash
    sleep 60
    

    Und hier die main.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <signal.h>
    #include <errno.h>
    
    #include <iostream>
    #include <thread>
    
    void thread_func()
    {
        pid_t pid = fork();
        if (pid == 0)
        {
            // Child code
            int status = system("/home/vbox/p.sh");
            exit(status);
        }
        // parent code welcher child überwachen soll
        pid_t c;
        int t_loop = 0;
        while (c == 0) {
            ++t_loop;                       // Pseudo timer
            c = waitpid(pid, 0, WNOHANG);   // Check ob Prozess noch läuft
            if (t_loop == 7) {              // Zeit ist um -> alles töten
                kill(pid);                  // Child ist tot und der sys_call hängt am init
                //system("kill pid")        // das selbe Problem auch mit pkill kein Erfolg
                break;                      // Thread kann beendet werden
            }
            sleep(1);
        }
    }
    
    int main()
    {
        std::thread t(thread_func);
        // do stuff
        sleep(3);
        t.join();
    
        return 0;
    }
    

    Wie erwähnt wird der sys_call nach dem Abbleben des Child-Prozesses an den init Prozess übergeben. Wie kann ich das verhindern? Wenn Child stirbt muss auch der sys_call sterben. Zu erwähnen wäre noch, das ich den Child-Prozess nur erstelle um den sys_call zu beenden (erfolglos). Ich habe auch nach einer Methode gesucht um an die PID des sys_calls zu kommen, aber keine Funktion gefunden die mir die PID zurück gibt ( system und Konsorten geben ja nur den Status zurück und blockieren solange bis alles fertig ist). Prinzipiell wird ja der sys_call auch geforkt, somit ist mein Child nur ein kleiner Workaround da ich es nicht besser weiss.

    Über Hilfe wäre ich dankbar.

    Schönen Abend noch.

    PS: Falls das wirklich jemand kompilieren will, so gehts:

    g++ -std=gnu++0x -o test main.cpp -pthread
    


  • Nachtrag:
    Ich sehe geade das in meinem Code-Schnipsel ein Fehler ist. Zeile 29 muss natürlich

    kill(pid, SIGTERM);
    

    heißen.



  • Versuch mal statt

    int status = system("/home/vbox/p.sh");
    

    das:

    int status = execl("/home/vbox/p.sh", "p.sh", NULL);
    


  • Nur mal so als off-topic Hinweis: Wenn Du was mit system aufrufst, dann ist das kein syscall, auch wenn der Name das suggeriert. Das Kommando system löst allerdings eine ganze Latte von syscalls. Syscalls gibt es relativ wenige. Die wichtigsten sind read, write, open, close, fork und exec. Linus Torvalds hat mal gesagt, dass ein Unix-System aus diesen 6 Systemaufrufen besteht.

    Dann doch was zum Thema: Wenn Du ein fork machst und dann mit system ein Shell-skript aufrufst, welcher sleep aufruft, dann erzeugst Du 3 Prozesse. Nämlich die Kopie Deines Prozesses, die Shell und das sleep. Mit kill erreichst Du nur den ersten. Der nächste in der Kaskade, also die Shell verliert einfach seinen Parent und wird dadurch von init geerbt. Das ist normales Verhalten.



  • ach Bloedsinn ...


Anmelden zum Antworten