PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C/C++] Lockfile



BLUESCREEN3D
29-04-2006, 18:33
Ich wollte ein Programm schreiben, dass nicht mit mehren Instanzen parallel in dem selben Verzeichnis laufen soll.
Dazu wollte ich beim Programmstart ein Advisory Lockfile in der dem Verzeichnis anlegen, das verhindert, dass weitere Instanzen des Programmes gleichzeitig laufen (diese sollen nicht auf den laufenden Prozess warten, sondern sich gleich wieder beenden, falls ein anderer Prozess läuft).

Mein erster Ansatz war, das ganze über open() mit O_EXCL zu realisieren. Das funktioniert soweit wie gewollt, hat aber einen Nachteil: Falls das Programm crasht bleibt das Lockfile bestehen und verhindert weitere Programmdurchläufe bis die Datei manuell entfernt wird.

Falls man stattdessen mit fcntl() arbeitet sind die Operationen nicht mehr atomar, da zwischen open() und fcntl() eine gewisse Zeit liegen kann.

Nun suche ich nach einer Möglichkeit, das ganze so zu realisieren, dass das System auch einen gecrashten Prozess übersteht ohne dauerhaft zu blockieren und gleichzeitig das Lockfile nur zu der Laufzeit der Prozesse vorhanden ist (eine Lösung, wo das Lockfile dauerhaft existiert und nur von Zeit zu Zeit mittels fcntl() gesperrt wird, wollte ich eigentlich nicht haben).

RapidMax
29-04-2006, 22:13
Der erste Ansatz mit open() und O_EXCL ist schon gut. Du solltest aber zusätzlich die PID in das File schreiben. Vor dem Anlegen der Datei prüfst du, ob die Datei bereits existiert, liest die PID aus und überprüfst, ob diese PID gerade läuft (kill(pid, 0)). Wenn nicht, kannst du die Datei löschen und wie beschrieben mit open(..., O_EXCL) neu erstellen.

Hier ist das ganze nochmals gut beschrieben:
http://www-128.ibm.com/developerworks/library-combined/l-sprace.html#N100BA

Gruss, Andy

BLUESCREEN3D
29-04-2006, 23:57
Dein Vorschlag enthält leider selbst eine Race Condition:

Angenommen ein erster Prozess crasht und hinterlässt ein Lockfile mit seiner PID.
Anschließend werden zwei weitere Prozesse gestartet.
Der erste davon liest die PID und merkt, dass es den Prozess nicht gibt.
Anschließend tut der zweite Prozess da gleiche.
Nun löscht der erste Prozess die Datei und erstellt eine neue Datei mit seiner eigenen PID.
Diese wird nun von dem zweiten Prozess gelöscht und schon laufen zwei Prozesse parallel...

Bei deinem Link werden zwar im ersten Absatz unter "Lock files" einige Ansätze beschrieben, was man gegen veraltete Lockfiles tun kann, aber die gefallen mir alle nicht:
Wenn der Prozess von einem anderen Prozess gestartet wird, der sich ums Locking kümmert, dann muss dieser Kontrollprozess selbst wieder geschützt werden.
Wenn alte Lockfiles nur beim Systemstart gelöscht werden, können sie das System sehr lange blockieren.
Wenn alte Lockfiles per Cronjob gesucht werden sollen, dann muss diese Suche selbst wieder gegen Race Conditions geschützt werden.

klewan
30-04-2006, 02:05
ich mach das meist im startup script ala

PIDF="/var/run/prog.pid";
PID_P=$(cat $PIDF);
PID_RUN="/proc/${PID_P}/cmdline"



if [ ! -f $PID_RUN ];
then
rm -f $PIDFILE
else
echo "running @ $PID_P";
exit 1;
fi;

anda_skoa
30-04-2006, 18:15
Übrigens ist laut man page O_EXCL abhängig vom Filesystem, geht zum Beispiel mit NFS nicht.

Ciao,
_

BLUESCREEN3D
07-05-2006, 19:17
Ich verwende nun fcntl() mit einem Lockfile, welches nicht gelöscht wird.
Alles andere bringt ja nichts...