staging.inyokaproject.org

Wie kann ein Programm feststellen ob es schon läuft?

Status: Gelöst | Ubuntu-Version: Xubuntu 14.04 (Trusty Tahr)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ok, der Titel ist etwas zu kurz wegen des Platzes in der Titelzeile.

Es geht darum, wie ein C oder C++ Programm feststellen kann, ob von ihm bereits eine Instanz läuft. Also so, wie etwa bei Gimp, wo ich im Bildbetrachter auswählen kann "öffnen mit Gimp" und dann nicht ein neues Gimp gestartet wird, sondern im bereits laufendem Gimp nur ein neues Bearbeitungsfenster geöffnet wird.

Ich möchte das u.a. dafür nutzen, das nur die erste gestartete Instanz eines Programms Konfigurationsdaten speichern können soll. Die anderen sollen nur lesen.

Seebär

Avatar von Seebär

Anmeldungsdatum:
2. Mai 2009

Beiträge: 833

Indem man z.B. ein heartbeat-File oder lock-File verwendet.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ok, das bedeutet, ich muss mich selber darum kümmern. Das kriege ich wohl irgendwie hin. Aber das bedeutet dann wohl auch, das ich mich im Falle eines Programm Absturzes irgendwie um die Hinterlassenschaften kümmern muss (meine Programme lieben es abzustürzen 😢 ).

Also ich erinnere mich da an die verwaisten Lock Dateien von Übertragungsprogrammen wie Minicom, die nach einem gewaltsamen Abbruch jedes mal manuell gelöscht werden mussten, um eine normale Funktion wieder herzustellen.

Ich hatte mir da etwas mehr Unterstützung vom Betriebssystem erhofft.

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

Theoretisch kannst du natürlich auch noch prüfen, ob es zu deinem Programm schon eine pid gibt (getenv o.ä.). Falls du dann eine .lock-Datei findest, aber keine pid, könntest du den Nutzer darauf hinweisen und fragen, ob wirklich keine weitere Instanz läuft und das die aktuelle im read-only-Modus läuft.
Bei mehreren Benutzern, die dein Programm starten müsstest du natürlich den Nutzernamen irgendwie im lock-File speichern und abfragen, da ansonsten ein zweiter Benutzer das Programm nicht mit Schreibzugriff starten kann, so lange es beim ersten noch läuft.

Dazu wäre vielleicht eine angepasste .desktop-Datei noch praktisch, da kann man weitere Instanzen mit Parameter aufrufen, wie z.B. bei Browsern (neuer Tab, private Session, etc. wie z.B. in der firefox.desktop oder google-chrome.desktop), wenn dein Programm das anbietet.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Also ich erinnere mich da an die verwaisten Lock Dateien von Übertragungsprogrammen wie Minicom, die nach einem gewaltsamen Abbruch jedes mal manuell gelöscht werden mussten, um eine normale Funktion wieder herzustellen.

Ich hatte mir da etwas mehr Unterstützung vom Betriebssystem erhofft.

Gibt es ja auch: du machst einfach ein exklusives Filelock auf die Datei. Das wird dann abgeräumt, wenn der Prozess terminiert. Das ganze geht sogar in der Shell (siehe "man flock", da ist auch der Verweis auf die Libc-Funktion gleichen Namens).

Eine andere Möglichkeit wäre, einen Socket zu öffnen. Über den könnten dann auch nachträglich gestartete Instanzen mit der ersten reden, um z.B. eine Aktion auszulösen oder eine Datei zu öffnen.

Unter einen DE wird vermutlich D-Bus verwendet, um eine bereits bestehende Instanz einer Anwendung zu finden und dazu aufzufordern, ein Dokument oder einen Browser-Tab zu öffnen. Da kenne ich mich aber nicht aus.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@Dakuan: Da Du Gimp erwähnst: die GtkApplication-Klasse beziehungsweise die GApplication-Klasse haben für so etwas Unterstützung. Unter Linux wird das dann über D-Bus abgewickelt.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

@ChickenLipsRfun2eat: An mehrere Benutzer hatte ich noch gar nicht gedacht. Aber ich habe oft 2 Instanzen eines Programms offen, damit ich Daten besser hin und her kopieren kann. Da ist es dann blöd, wenn die sich nicht einigen können wessen Fensterposition gespeichert werden soll.

@rklm: Das mit dem flock werde ich mir mal genauer ansehen.

Eine andere Möglichkeit wäre, einen Socket zu öffnen.

Mit Sockets habe ich mich noch nicht beschäftigt. Das erschien mir bisher zu kompliziert und zu umfangreich.

@Marc_BlackJack_Rintsch: Gimp war das erste Programm, wo mir das aufgefallen ist. Aber Gimp geht da wohl noch einen Schritt weiter, indem das eigentliche Programm nur einmal gestartet wird und bei Bedarf nur weitere Fenster dazu kommen.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Gimp und Konsorten "telefonieren" alle auf dem dbus (mit eindeutigen Adressen !) - Schau es Dir einfach mal an:

track@track:~$ dbus-monitor 
[...]
signal sender=org.freedesktop.DBus -> dest=(null destination) serial=7 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.107"
   string ""
   string ":1.107"
method call sender=:1.107 -> dest=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello
method call sender=:1.107 -> dest=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.gimp.GIMP.UI',path='/org/gimp/GIMP/UI',interface='org.gimp.GIMP.UI'"
method call sender=:1.107 -> dest=org.freedesktop.DBus serial=3 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
   string "type='signal',sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.gimp.GIMP.UI'"
method call sender=:1.107 -> dest=org.freedesktop.DBus serial=6 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RemoveMatch
   string "type='signal',sender='org.gimp.GIMP.UI',path='/org/gimp/GIMP/UI',interface='org.gimp.GIMP.UI'"
method call sender=:1.107 -> dest=org.freedesktop.DBus serial=7 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RemoveMatch
   string "type='signal',sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.gimp.GIMP.UI'"
signal sender=org.freedesktop.DBus -> dest=(null destination) serial=8 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string "org.gimp.GIMP.UI"
   string ""
   string ":1.107"
[usw. ...] 

Das wäre wohl die Methode der Wahl, wenn jetzt nicht besonders portabel (nach Win.. oder so) sein muss.

LG,

track

encbladexp Team-Icon

Ehemaliger
Avatar von encbladexp

Anmeldungsdatum:
16. Februar 2007

Beiträge: 17531

dbus hat auch den Vorteil das man nach einem Absturz von System nicht lockfiles suchen muss weil die Anwendung nicht mehr aufgeht und die Datei noch vorhanden ist.

mfg Stefan

Seebär

Avatar von Seebär

Anmeldungsdatum:
2. Mai 2009

Beiträge: 833

Dakuan schrieb:

Mit Sockets habe ich mich noch nicht beschäftigt. Das erschien mir bisher zu kompliziert und zu umfangreich.

Das wird nicht so wild und lösbar sein. Ist auch portabel und bietet - wie z.B. dbus - den Vorteil sich nicht um die Files kümmern zu müssen. Dafür musst dich halt um sockets kümmern. Nachteil ist dann: welchen Port nimmst du? Nimmst du einen fixen Port, läufst du Gefahr, dass eine andere Anwendung den verbraten hat. Dann musst du mindestens den Port konfigurieren können. Oder du machst es flexibel (z.B. ein freier Port im Range 61000..61099), dann musst die Anwendung aber auch den Port iwie mitteilen (z.B. wieder per File, ähnliches Thema wie vorher)

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ich erkenne gerade, wie groß die Wissenslücken sind, die ich unbearbeitet vor mir her schiebe. Das abzustellen dauert etwas. Daher möchte ich Sockets und D-Bus erstmal zurück stellen.

Aber könnte es funktionieren, wenn ich einen flock auf die Konfigurationsdatei mache. Zumindest müsste ich dann die User ID nicht prüfen da jeder seine eigene hat. Aus meinem Buch "Linux-Unix-Programmierung" kann ich nicht eindeutig herauslesen ob das funktionieren kann.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Aber könnte es funktionieren, wenn ich einen flock auf die Konfigurationsdatei mache.

Ja, das ist auf jeden Fall ein gangbarer Weg. Idealerweise öffnest Du die dann mit O_CREAT (siehe man open) und holst danach sofort die exklusive Sperre. Nur, wenn beides klappt, geht es weiter. Sonst ist ein Doppelgänger da und Du terminierst, ohne in die Datei geschrieben zu haben!

Zumindest müsste ich dann die User ID nicht prüfen da jeder seine eigene hat.

Genau.

Aus meinem Buch "Linux-Unix-Programmierung" kann ich nicht eindeutig herauslesen ob das funktionieren kann.

Ich kenne das Buch nicht, aber vielleicht ist es dann nicht so toll.

encbladexp schrieb:

dbus hat auch den Vorteil das man nach einem Absturz von System nicht lockfiles suchen muss weil die Anwendung nicht mehr aufgeht und die Datei noch vorhanden ist.

Das ist aber nur der Fall, wenn man die Existenz der Datei als Kriterium für das Laufen nimmt. Die robustere Methode ist via flock(). Die Datei kann dann sowieso immer liegen bleiben (oder man nimmt gleich die Konfigurationsdatei, wie vorgeschlagen wurde).

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ok, damit ist der Weg erstmal vorgezeichnet. Ich muss jetzt nur noch herausfinden, wie ich meinem FLTK Toolkit das unterjubeln kann. Möglicherweise gibt es da eine kleine unsichere Zeitspanne. Aber ich hoffe, dass die kürzer ist als die Zeit, die ein Benutzer benötigt um ein zweites Programm zu starten.

Ich kenne das Buch nicht, aber vielleicht ist es dann nicht so toll.

Ist auch schon etwas älter. Hatte ich kurz nach meiner Forumanmeldung angeschafft und war damals das einzige, was ich finden konnte. In letzter Zeit lese ich allerdings öfters, das die Bücher von Herrn Wolf nicht so gut angesehen sind. Aber es war mein Einstieg.

Nur, wenn beides klappt, geht es weiter. Sonst ist ein Doppelgänger da und Du terminierst, ohne in die Datei geschrieben zu haben!

Ganz so radikal möchte ich es nicht machen. Also bestimmte Dinge sollten evtl. lesbar sein (könnte ich aber auch drauf verzichten), aber auf jeden Fall soll schreiben verhindert werden. Also das zweite Programm soll schon starten, aber die Konfig nicht ändern dürfen.

Ich denke das ist dann ein Verhalten, auf das sich ein Benutzer einstellen kann.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Ok, damit ist der Weg erstmal vorgezeichnet. Ich muss jetzt nur noch herausfinden, wie ich meinem FLTK Toolkit das unterjubeln kann.

Was hat das mit dem Toolkit zu tun? Du würdest das doch irgendwo in main() machen, bevor Du irgendetwas anderes machst.

Möglicherweise gibt es da eine kleine unsichere Zeitspanne.

Kann es nicht. Wo sollte das sein?

Ich kenne das Buch nicht, aber vielleicht ist es dann nicht so toll.

Ist auch schon etwas älter. Hatte ich kurz nach meiner Forumanmeldung angeschafft und war damals das einzige, was ich finden konnte. In letzter Zeit lese ich allerdings öfters, das die Bücher von Herrn Wolf nicht so gut angesehen sind. Aber es war mein Einstieg.

Ist ja auch in Ordnung. Manche Bücher sind gut als Einführung, helfen dann aber ab einem bestimmten Punkt nicht mehr weiter und man muss sich dann anders orientieren.

Nur, wenn beides klappt, geht es weiter. Sonst ist ein Doppelgänger da und Du terminierst, ohne in die Datei geschrieben zu haben!

Ganz so radikal möchte ich es nicht machen. Also bestimmte Dinge sollten evtl. lesbar sein (könnte ich aber auch drauf verzichten), aber auf jeden Fall soll schreiben verhindert werden. Also das zweite Programm soll schon starten, aber die Konfig nicht ändern dürfen.

Ich denke das ist dann ein Verhalten, auf das sich ein Benutzer einstellen kann.

Ich dachte, Du wolltest sicherstellen, dass das Programm nur ein Mal läuft. Geht es Dir nur darum, dass die Datei nicht von mehreren gleichzeitig geschrieben wird?

barcc

Avatar von barcc

Anmeldungsdatum:
13. Juli 2007

Beiträge: 696

Dakuan schrieb:

@ChickenLipsRfun2eat: ... Aber ich habe oft 2 Instanzen eines Programms offen, damit ich Daten besser hin und her kopieren kann. Da ist es dann blöd, wenn die sich nicht einigen können wessen Fensterposition gespeichert werden soll.

Wenn es nur darum geht, sehe ich hier überhaupt kein Problem. Beim Programmende wird die Fensterposition gespeichert. Die zuletzt geschlossene Instanz bestimmt dann die Position beim Neustart. Übrigens ist es eine weit verbreitete Meinung, dass die Fensterposition überhaupt nicht gespeicher werden soll, die Fensterposition zu bestimmen ist Aufgabe des Betriebssystems. Konfigurationsdateien für einzelne Instanzen zu sperren ist eher eine bizarre Idee.

Antworten |