Hallo Leute,
habe folgendes Problem:
Aus einer Applikation (App1) heraus wird mittels system(aufruf) eine zweite Applikation (App2) gestartet.
Ich möchte verhindern, das dies Applikation App2 mehrmals aus App1 gestartet werden kann! Und ich möchte aus App1 an App2 ein Signal schicken wenn ein zweites mal versucht wird App2 zu starten.
Leider bekomme man bei dem Aufruf von System nicht die PID zurück sondern nur ob es geklappt hat oder nicht!
Für den Signalhandler benötige ich aber die PID!
Aber wie ermittele ich diese am besten?
Kann mir jemand helfen?
Konsolenaufruf und SIGNAL
system() ist für sowas ungeeignet, da der aufrufende Prozess wartet, bis das aufgerufene Programm beendet ist. system() ist eine Abkürzung für "naive" Prozesse, die nichts vom Multitasking wissen müssen -- system() ist im C-Standard definiert und muss also auch z.B. unter DOS funzen.
Nimm stattdessen fork() und execve(), wenn du die Unix-Semantik brauchst.
Janka
Nimm stattdessen fork() und execve(), wenn du die Unix-Semantik brauchst.
Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
Ich mag die Schreie.
$ man 2 readlink
Aber das ist sowieso der falsche Weg. Der richtige Weg ist es, sich mit flock() ein Lock auf das Executable der Applikation zu beschaffen und auf *dieses* zu testen, nicht auf den *Namen* der Applikation.
So in etwa:
Im Beispiel oben wartet eine Applikation im flock() so lange, bis ihre Schwester mit dem gleichen Executable beendet wurde. Und das vollautomatisch!
Janka
Aber das ist sowieso der falsche Weg. Der richtige Weg ist es, sich mit flock() ein Lock auf das Executable der Applikation zu beschaffen und auf *dieses* zu testen, nicht auf den *Namen* der Applikation.
So in etwa:
Code: Select all
if ((app_fd=open("/proc/self/exe", O_RDONLY)) == -1) {
perror("cannot lock against multiple invocation");
exit(EXIT_FAILURE);
}
if (flock(app_fd, LOCK_EX) == -1) {
perror("cannot lock against multiple invocation");
exit(EXIT_FAILURE);
}
Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
Ich mag die Schreie.
Aber das löst mein Problem nicht(zumindest ist es mir nicht gelungen!)!
Vorgehensweise:
- einen filedescriptor fd
- darauf führe ich ein lock aus, wenn ich diese Applikation starten will.
Dieses muss "flock (fd, LOCK_EX| LOCK_NB)" sein weil die zweite Applikation nur einmal gestartet werden soll und beim zweiten aufruf nichts passieren soll!
Problem ist, dass die zweite Applikation aus dem gleichen Prozess (erste Applikation) heraus mehrmals gestartet werden kann!
Oder habe ich das Konzept nicht verstanden?
Vorgehensweise:
- einen filedescriptor fd
- darauf führe ich ein lock aus, wenn ich diese Applikation starten will.
Dieses muss "flock (fd, LOCK_EX| LOCK_NB)" sein weil die zweite Applikation nur einmal gestartet werden soll und beim zweiten aufruf nichts passieren soll!
Problem ist, dass die zweite Applikation aus dem gleichen Prozess (erste Applikation) heraus mehrmals gestartet werden kann!
Oder habe ich das Konzept nicht verstanden?
So wie du es machen willst, kann du es folgendermaßen tun:
fd muss ein Filedeskriptor auf das Executeable der zweiten Applikation sein, also nicht wie bei mir auf /proc/self/exe, sondern auf <Pfad zum Executeable der zweiten Applikation>. Den hast du ja sowieso, weil du danach execve() machen willst.
Dann machst du, wie du richtig rausgefunden hast, ein flock(fd, LOCK_EX|LOCK_NB) und guckst, ob EWOULDBLOCK zurückkommt. Wenn ja, machst du gar nichts, wenn nein, kannst du die andere Applikation starten. Das funktioniert natürlich nur mit kooperativen Prozessen, d.h. Applikation 2 muss grundsätzlich aus Applikation 1 heraus aufgerufen werden, weil ja sonst das Lock nicht abgefragt wird. Da du ja nicht genauer geschrieben hast, was Applikation 1 und Applikation 2 sind, gehe ich von kooperativen Prozessen aus.
Grundsätzlich hast du mit deiner Vorgehensweise aber das Problem, dass zwischen dem Abfragen, ob die zweite Applikation bereits gestartet ist und dem Moment, wo du die zweite Applikation startest ein Loch besteht, in dem die zweite Applikation bereits von extern gestartet werden konnte. Das ist sehr wackelig programmiert.
Deshalb ist es grundsätzlich ratsam, dass eine Applikation immer *selbst* prüft, ob bereits ein anderer Prozess mit demselben Executable gestartet wurde und danach blockiert oder sich selbst gleich wieder beendet. So entsteht kein Loch.
Janka
fd muss ein Filedeskriptor auf das Executeable der zweiten Applikation sein, also nicht wie bei mir auf /proc/self/exe, sondern auf <Pfad zum Executeable der zweiten Applikation>. Den hast du ja sowieso, weil du danach execve() machen willst.
Dann machst du, wie du richtig rausgefunden hast, ein flock(fd, LOCK_EX|LOCK_NB) und guckst, ob EWOULDBLOCK zurückkommt. Wenn ja, machst du gar nichts, wenn nein, kannst du die andere Applikation starten. Das funktioniert natürlich nur mit kooperativen Prozessen, d.h. Applikation 2 muss grundsätzlich aus Applikation 1 heraus aufgerufen werden, weil ja sonst das Lock nicht abgefragt wird. Da du ja nicht genauer geschrieben hast, was Applikation 1 und Applikation 2 sind, gehe ich von kooperativen Prozessen aus.
Grundsätzlich hast du mit deiner Vorgehensweise aber das Problem, dass zwischen dem Abfragen, ob die zweite Applikation bereits gestartet ist und dem Moment, wo du die zweite Applikation startest ein Loch besteht, in dem die zweite Applikation bereits von extern gestartet werden konnte. Das ist sehr wackelig programmiert.
Deshalb ist es grundsätzlich ratsam, dass eine Applikation immer *selbst* prüft, ob bereits ein anderer Prozess mit demselben Executable gestartet wurde und danach blockiert oder sich selbst gleich wieder beendet. So entsteht kein Loch.
Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
Ich mag die Schreie.