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 dersys_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 dersys_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 dersys_call
sterben. Zu erwähnen wäre noch, das ich den Child-Prozess nur erstelle um densys_call
zu beenden (erfolglos). Ich habe auch nach einer Methode gesucht um an diePID
dessys_calls
zu kommen, aber keine Funktion gefunden die mir diePID
zurück gibt (system
und Konsorten geben ja nur den Status zurück und blockieren solange bis alles fertig ist). Prinzipiell wird ja dersys_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ürlichkill(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 ...