Konsolenaufruf und SIGNAL

Post Reply
Message
Author
grisu1972
Posts: 16
Joined: 22. Jul 2008 11:03

Konsolenaufruf und SIGNAL

#1 Post by grisu1972 »

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?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#2 Post by Janka »

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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

grisu1972
Posts: 16
Joined: 22. Jul 2008 11:03

#3 Post by grisu1972 »

Hallo Leute,

ich durchsuche das /proc Verzeichnis nach meinem Prozess.
Dabei habe ich das Problem, dass dort der Name exe lautet und mit meiner Applikation verlinkt ist!

Wie bekomme ich aus dem link namen den "richtigen" Namen?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#4 Post by Janka »

$ 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:

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);
  }
Im Beispiel oben wartet eine Applikation im flock() so lange, bis ihre Schwester mit dem gleichen Executable beendet wurde. Und das vollautomatisch!

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

grisu1972
Posts: 16
Joined: 22. Jul 2008 11:03

#5 Post by grisu1972 »

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?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#6 Post by Janka »

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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Post Reply