Und "readdir" "besser" abfangen? Also mit eigener Logik "thread safe" machen?
Gruß
Frank
Und "readdir" "besser" abfangen? Also mit eigener Logik "thread safe" machen?
Gruß
Frank
Ich hab mir das eben noch mal durchgelesen. Wenn ich das richtig verstehe, dann kommt das Threadproblem eigentlich nur zustande, wenn man readdir aus verschiedenen Threads mit dem gleichen DIR struct aufruft. Solange aber opendir/readdir im gleichen Thread und nur in einem Thread benutzt wird, sollte es gar kein Problem geben. Oder sehe ich das falsch?
https://ftp.gnu.org/old-gnu/Ma…3/html_node/libc_262.html
https://www.gnu.org/software/l…02fClosing-Directory.html
Lars
Das siehst du sicher richtig. Aber wer garantiert dafür, daß das nicht passiert?
Klaus
Liefern denn zwei opendir auf dem gleichen Verzeichnis in zwei Threads das selbe DIR struct zurück? Müsste man sonst mit einer alten glibc mal ausprobieren, würde mich aber wundern.
Gibt es Stellen im vdr, wo der DIR Pointer z.B. in einem Member gespeichert wird und verschiedene Threads ihn benutzen?
Lars
Spontan sehe ich nur lokale Schleifen, wo die Klasse cReadDir benutzt wird.
Ach ja, text2skin könnte einfach diese Klasse benutzen, dann muss man nur im vdr etwas ändern, falls es Not tut.
Lars
Es wurde damals extra auf die thread-safe Versionen einiger Funktionen umgestiegen, um eventuelle Probleme zu vermeiden. Jetzt einfach wieder auf die "alte" Variante zurückzugehen und zu hoffen, daß schon alles klappen wird, ist sicher nicht der richtige Weg. Ich finde es auch reichlich dämlich von den libc-Entwicklern, erst eine readdir_r() zu machen und dann, viele Jahre später, die ursprüngliche Funktion zu fixen und readdir_r() zu deprecaten! Diese Funktion wird wohl sicherlich in sehr vielen Programmen verwendet, und ich kann mir nicht vorstellen, daß die jetzt alle mit wehenden Fahnen einfach so umstellen.
VDR wird weiterhin readdir_r() verwenden, es sei denn, es gibt eine Möglichkeit zur Compilezeit zu erkennen, daß readdir() tread-safe ist, oder daß es readdir_r() nicht mehr gibt, was ja wohl impliizit bedeutet, daß readdir() safe ist. Zum Glück wird readdir_r() ja nur innerhalb cReadDir benutzt, so daß man das sehr lokal regeln kann. Wenn jemand weiß, wie entsprechende #if Statements aussehen könnten, immer her damit.
Klaus
Ich verstehe auch nicht, was die libc Entwickler da geritten hat...
Da ich jetzt aus dem Urlaub zurück bin, werde ich mal versuchen, etwas in diese Richtung herauszufinden.
Lars
#if __GLIBC__ == 2 && __GLIBC_MINOR__ > 23
// readdir_r() is deprecated as of glibc-2.24
#else
// use readdir_r()
#endif
Alternativ..
#define GLIBCVER (100*__GLIBC__ + __GLIBC_MINOR__)
#if GLIBCVER >= 224
Ja, so fängt man die GLIBC Version ab, was aber wenn man "readdir" thread safe benötigt weil readdir_r nimmer zur Verfügung steht, z.B. im VDR?
Ignoriert mal bitte text2skin ... das ist kleines oder kein Problem ...
Regards
fnu
ZitatIn the current POSIX.1 specification (POSIX.1-2008), readdir(3) is
not required to be thread-safe. However, in modern
implementations (including the glibc implementation), concurrent
calls to readdir(3) that specify different directory streams are
thread-safe.
Damit sind wir wieder beim Anfang der Diskussion ... ich kenne das Zitat, scheint aber für wenig Überzeugung zu sorgen ...
Das ist IMO ein eindeutiges Statement.
1) glibc muss aktuell sein, ab der Version die das deprecated kann man fest davon ausgehen
2) das Argument von readdir() darf von keinem anderen Thread benutzt werden
kann man für 1) und 2) garantieren, gibt es kein Problem.
Die zweite Variante von wirbel finde ich besser, da damit dann auch glibc ab Version 3 abgedeckt ist. Die erste würde dann nicht mehr funktionieren.
Alternativ, falls die Minor-Version mal über 100 gehen sollte:
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 23)
// readdir_r() is deprecated as of glibc-2.24
#else
// use readdir_r()
#endif
Lars.
Nachdem es ja das Macro __GLIBC_PREREQ() gibt werde ich das so machen:
--- ./tools.h 2017/06/11 10:00:49 4.12
+++ ./tools.h 2017/06/25 11:45:38
@@ -400,10 +400,12 @@
private:
DIR *directory;
struct dirent *result;
+#if !__GLIBC_PREREQ(2, 24) // readdir_r() is deprecated as of GLIBC 2.24
union { // according to "The GNU C Library Reference Manual"
struct dirent d;
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
} u;
+#endif
public:
cReadDir(const char *Directory);
~cReadDir();
--- ./tools.c 2017/06/23 09:39:45 4.7
+++ ./tools.c 2017/06/25 11:45:39
@@ -1528,7 +1528,11 @@
struct dirent *cReadDir::Next(void)
{
if (directory) {
+#if !__GLIBC_PREREQ(2, 24) // readdir_r() is deprecated as of GLIBC 2.24
while (readdir_r(directory, &u.d, &result) == 0 && result) {
+#else
+ while ((result = readdir(directory)) != NULL) {
+#endif
if (strcmp(result->d_name, ".") && strcmp(result->d_name, ".."))
return result;
}
Alles anzeigen
Klaus
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!