"race condition" bei Verwendung von system() ?

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
dakuan
Beiträge: 97
Registriert: 28.04.2011 22:09:39

Re: "race condition" bei Verwendung von system() ?

Beitrag von dakuan » 25.05.2021 22:34:12

Konkret heisst das, dass `display' die Datei problemlos weiterhin anzeigen kann und auch neu darin lesen kann falls noetig, ungeachtet dessen, dass sie aus dem Dateisystem ``geloescht'' worden ist.
Das verunsichert mich jetzt wieder, zumal so etwas im oben genannten Buch auch erwähnt wurde. Vielleicht muss ich da doch noch länger testen.
Das Kommentarhinzufügen ist damit quasi atomar und kann display nicht stören.
Das rename ist tatsächlich atomar. Das hatte ich kürzlich in der Argumentation von
Thumbnail Saving (weiter bis: Concurrent Thumbnail Creation) gelesen. Aber das bezog sich nur auf gleichzeitiges schreiben.

Da muss ich wohl noch weiter forschen. 60 Tests sind da möglicherweise noch zu wenig.

JTH
Moderator
Beiträge: 3014
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: "race condition" bei Verwendung von system() ?

Beitrag von JTH » 25.05.2021 23:50:10

So direkt fällt mir dazu auch nichts mehr ein, da ein Datei-wird-gelesen-während-sie-überschrieben-wird durch das Verschieben ja anscheinend wegfällt.

dakuan hat geschrieben: ↑ zum Beitrag ↑
25.05.2021 22:34:12
Da muss ich wohl noch weiter forschen.
dakuan hat geschrieben: ↑ zum Beitrag ↑
25.05.2021 21:03:28
Der komplette Quelltext ist eigentlich auch nicht geheim, aber wo soll ich den hinladen?
Wenn du noch an einem zweiten oder dritten Paar Augen interessiert bist (und damit Meillo mangels Glaskugel nicht bald zu schwarzer Magie greift), kannst du deinen Code gerne nach NoPaste kopieren. Alle 1300 Zeilen müssen es vielleicht nicht direkt sein, aber ein deutlich größerer, zusammenhängender Ausschnitt des Ablaufs hier und eine der Kommentarfunktionen könnten helfen.
Manchmal bekannt als Just (another) Terminal Hacker.

dakuan
Beiträge: 97
Registriert: 28.04.2011 22:09:39

Re: "race condition" bei Verwendung von system() ?

Beitrag von dakuan » 26.05.2021 18:32:29

Alle 1300 Zeilen müssen es vielleicht nicht direkt sein, aber ein deutlich größerer, zusammenhängender Ausschnitt des Ablaufs hier und eine der Kommentarfunktionen könnten helfen.
Ok, ich versuche es mal. hier erstmal der Teil des Programms, der den Auftrag erstellt:
NoPaste-Eintrag41387

Und hier ein Kommentarmodul. Interessanst ist da die Funktion png_put_com():
NoPaste-Eintrag41388
p.s. der CRC Generator ist aus dem Buch: "Compressed Image File Formats" von John Miano.

JTH
Moderator
Beiträge: 3014
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: "race condition" bei Verwendung von system() ?

Beitrag von JTH » 26.05.2021 19:51:33

Am Rande: ImageMagick hat auch eine C-API – falls du mal zu viel Freizeit hast und die system() ersetzen willst ;)

Ansonsten: Ich nehme mal an, ENABLE_ALL_COM ist definiert? Falls nicht, dürfte der jhead-Aufruf das ursprünglich vermutete Problem auslösen, der überschreibt, was display versucht parallel zu lesen:

Code: Alles auswählen

    if ( strlen( rembuf ) ){ /* Kommentar einfuegen lassen */
        sprintf( workbuf, "jhead -cl \"%s\" \"%s\" > /dev/null", rembuf, img->name );
        system( workbuf );
    }

Andernfalls wäre meine nächste Vermutung, dass display versucht, die Datei zu lesen, wenn sie hier

Code: Alles auswählen

                remove( fname );
                rename( img_tname, fname );
im *_put_com() gerade gelöscht ist. In irgendeiner Form muss das ja basierend auf der ursprünglichen Fehlermeldung
dakuan hat geschrieben: ↑ zum Beitrag ↑
25.05.2021 16:25:45

Code: Alles auswählen

display-im6.q16: unable to open image `Traktor1.jpg': Datei oder Verzeichnis nicht gefunden @ rror/blob.c/OpenBlob/2701.
display-im6.q16: no decode delegate for this image format `' @ error/constitute.c/ReadImage/504.
der Fall sein.

Ich hab mal ein strace auf einen display-Aufruf laufen lassen. display öffnet (hier zumindest) die Datei insgesamt dreimal – und schließt sie auch zwischendurch wieder:

Code: Alles auswählen

$ strace -o strace.txt -e open,openat,stat,access,close display test.jpg
stat("test.jpg", {st_mode=S_IFREG|0600, st_size=20052, ...}) = 0
access("test.jpg", F_OK)             = 0
[…]
stat("test.jpg", {st_mode=S_IFREG|0600, st_size=20052, ...}) = 0
openat(AT_FDCWD, "test.jpg", O_RDONLY) = 4
close(4)                                = 0
[…]
stat("test.jpg", {st_mode=S_IFREG|0600, st_size=20052, ...}) = 0
openat(AT_FDCWD, "test.jpg", O_RDONLY) = 4
close(4)                                = 0
stat("test.jpg", {st_mode=S_IFREG|0600, st_size=20052, ...}) = 0
openat(AT_FDCWD, "test.jpg", O_RDONLY) = 4
close(4)
[…]
Neben einigen stat() und access()-Aufrufen. Das mehrfache Öffnen ist, vermute ich mal, zum anfänglichen Ermitteln des Dateityps (niemand verlässt sich auf Dateiendungen) und schließlich tatsächlichen Auslesen der Inhalte. Wenn die Datei bei einem der drei Öffnungsversuche gerade gelöscht ist, würde das zu obigem typischen

Code: Alles auswählen

Datei oder Verzeichnis nicht gefunden
passen.
Manchmal bekannt als Just (another) Terminal Hacker.

dakuan
Beiträge: 97
Registriert: 28.04.2011 22:09:39

Re: "race condition" bei Verwendung von system() ?

Beitrag von dakuan » 26.05.2021 20:51:23

Das mit dem C-API ist mir im Prinzip bekannt. Aber als ich mir das damals ansehen wollte, hatte ich irgendwie Probleme mit der Doku.

Heute würde ich das lieber mit eigenen Funktionen machen wollen. Ich benötige ja nur einfache Grundfunktionen. Gescheitert ist das bisher an den Schriften.
Ich nehme mal an, ENABLE_ALL_COM ist definiert?
Ja, die Verwendung von jhead ist eine Altlast. Und .PNG oder .GIF geht damit auch nicht.
display öffnet (hier zumindest) die Datei insgesamt dreimal – und schließt sie auch zwischendurch wieder:
Das vergrößert das Fehlerfenster natürlich deutlich, je nach dem wie lang die "Öffnungszeiten" jeweils sind. Ich habe strace nur einmal laufen lassen. Die Menge der Ausgaben hat mich umgehauen...
Das mehrfache Öffnen ist, vermute ich mal, zum anfänglichen Ermitteln des Dateityps
Normalerweise kann man das alles in einem Rutsch machen. Aber größere Programme sind ja meist modular aufgebaut. Dateityp prüfen wird ja auch benötigt, wenn man nur den Kommentar-Bereich lesen will. Im Beispiel wäre das:

Code: Alles auswählen

ReadSignature()
Ich könnte ja mal zum Testen ein anderes Programm zur Anzeige verwenden, vielleicht feh.

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: "race condition" bei Verwendung von system() ?

Beitrag von Meillo » 27.05.2021 21:50:24

Wenn `display' die Datei mehrmals oeffnet kann das das Problem sein. Das sehe ich wie JTH. Warum `display' das jedoch tut erschliesst sich mir nicht, weil man, um die Datei mehrmals zu lesen, ja auch einfach rewind(3) nehmen koennte. Nun gut, so ist es halt.

Versuche ruhig mal `feh' oder `qiv' oder `sxiv' oder so (die letzteren zwei sind etwas minimalistischer). Wenn die die Datei nur einmal oeffnen, dann koennte das das Problem loesen.

Dass dich die Ausgabe von `strace' erschlaegt, wundert mich nicht. Das ist die Erfahrung jeder Person, die das Programm zum ersten Mal verwendet. ;-) Du musst dann halt geeignet auf einzelne Syscalls einschraenken oder in der Ausgabedatei effizient suchen.
Use ed once in a while!

dakuan
Beiträge: 97
Registriert: 28.04.2011 22:09:39

Re: "race condition" bei Verwendung von system() ?

Beitrag von dakuan » 27.05.2021 23:24:27

Warum `display' das jedoch tut erschliesst sich mir nicht, weil man, um die Datei mehrmals zu lesen, ja auch einfach rewind(3) nehmen koennte.
In gewisser Weise könnte ich das schon verstehen. Das könnte z.B. von der Schnittstelle der Funktion abhängen, Also wenn der Dateipfad übergeben werden muss oder ein gültiger Filepointer. Ich hatte z.B. schon den Fall, das ich in einem C++ Programm Daten von einer Datei brauchte, die ein bereits vorhandenes C-Programm liefern kann. Da ist dann allerdings die Schnittstelle eine andere.

Aber bei einem Programm "aus einem Guss" kann ich das auch nicht verstehen und versuche das zu vermeiden. Man kann das auch an meinem Beispielprogramm sehen, wo z.B. die Funktion png_get_size() (die im aktuellen Fall nicht verwendet wird) der Funktion ReadSignature() einen bereits vorhandenen File-Pointer übergibt.

Aber um die Gründe dafür zu ermitteln, möchte ich jetzt nicht in den Quelltext von 'display' einsteigen. Ich kämpfe schon genug mit dem Quelltext von FLTK um festzustellen, ob ein Fehler jetzt bei mir liegt oder ob es ein Bug ist (habe da schon 3 entdeckt, die inzwischen gefixt sind).

Also feh als Anzeigeprogramm wollte ich schon ausprobiert haben. Aber durch die Änderungen in den letzten Tagen, habe ich neue Probleme mit der Anordnung der Elemente, die allerdings keine Auswirkung auf das Problem haben, aber für mich eine höhere Priorität haben.
Dass dich die Ausgabe von `strace' erschlaegt, wundert mich nicht.
Das man da irgendwie filtern kann, war mir bisher nicht bekannt. Wenn ich wüsste, worauf man da triggern muss, könnte man den bisherigen Verdacht bestätigen oder wiederlegen. Problem ist da aber, das es ca. 10 bis 20 Versuche braucht, um das Problem zu provozieren.

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: "race condition" bei Verwendung von system() ?

Beitrag von Meillo » 29.05.2021 09:16:52

dakuan hat geschrieben: ↑ zum Beitrag ↑
27.05.2021 23:24:27
Also feh als Anzeigeprogramm wollte ich schon ausprobiert haben. Aber durch die Änderungen in den letzten Tagen, habe ich neue Probleme mit der Anordnung der Elemente, die allerdings keine Auswirkung auf das Problem haben, aber für mich eine höhere Priorität haben.
Das finde ich vernuenftig. Melde dich einfach wieder wenn du dich erneut damit beschaeftigst.
Dass dich die Ausgabe von `strace' erschlaegt, wundert mich nicht.
Das man da irgendwie filtern kann, war mir bisher nicht bekannt. Wenn ich wüsste, worauf man da triggern muss, könnte man den bisherigen Verdacht bestätigen oder wiederlegen. Problem ist da aber, das es ca. 10 bis 20 Versuche braucht, um das Problem zu provozieren.
Du musst dir das Argument `-e' in der Manpage anschauen. Damit kannst du sagen welche Systemcalls du sehen willst. Wenn du `strace -e open' verwendest bekommst du nur alle Aufrufe von open(2) ausgegeben. Wenn du `strace -e trace=file' verwendest bekommst du alle File-bezogenen Systemcalls ausgegeben, das sind viele.

Sonst ist noch `-f' relevant. Wenn du das verwendest werden auch Kindprozesse getract, sonst nicht.

`strace' ist halt ein Hilfsmittel, das du einsetzen kannst um dem Problem auf die Spur zu kommen, weil es zeigt was wirklich passiert.
Use ed once in a while!

dakuan
Beiträge: 97
Registriert: 28.04.2011 22:09:39

Re: "race condition" bei Verwendung von system() ?

Beitrag von dakuan » 29.05.2021 18:47:43

Ich habe das jetzt mal mit feh und sxiv ausprobiert - Problem bleibt.

Code: Alles auswählen

feh WARNING: Traktor2.jpg does not exist - skipping
feh: No loadable images specified.
See 'man feh' for detailed usage information

Code: Alles auswählen

sxiv: Traktor2.jpg: No such file or directory
sxiv: No valid image file given, aborting
Zusätzlich habe ich auch mal ein eigenes Programm genommen, weil ich da weiß was es macht. Aber da ist nichts passiert. Dabei wird die Datei da auch zweimal geöffnet, einmal mit einer Bibliotheksfunktion um das Bild zu laden und danach von meinem Code um nach einem Kommentar zu suchen.

Verstehen tue ich das alles nicht. Wenn man davon ausgeht, das genau die Lücke zwischen remove() und rename() getroffen werden muss, sollt das Problem viel seltener auftreten.

Aber mit strace sollte ich mich wohl doch noch mal beschäftigen. Bei meinem ersten Versuch hatte ich das auf ein Grafisches Programm losgelassen. Da genügte eine Bewegung und der Bildschirm war vollgemüllt.

Antworten