Vous n'êtes pas identifié.
Hello,
j'ai un problème au niveau du multi-threading concernant les fonctions pipe(), fork(), dup2(), et close() qui ne sont (à prioris) pas MT-Safe. A noter que dans la doc de la glibc je ne trouve pas d'informations explicite. Mais du coup ça me pose un problème majeur (dans un cas d'utilisation précis) avec une bibliothèque sur laquelle je bosse.
Je m'explique.. cette bibliothèque utilise abondamment des threads ainsi que des fork(). Il y a un superviseur qui sérialise les fonctions de l'API public pour garantir d'être MT-Safe. Mais, il y a un superviseur par handle et non un seul superviseur global pour tout le monde.
En général on utilise la lib qu'avec un seul handle, donc un seul superviseur et la vie est belle. Rien n'est global donc il est également possible de créer plusieurs handles (donc plusieurs superviseurs). Le tout étant compilé avec -D_REENTRANT la majorité des fonctions sont suffisamment safes. Par contre il se peut, si l'application qui utilise la lib est également multi-threads, qu'il y ait donc deux fork(), pipe(), etc qui se produisent en même temps.
Et la où ça devient encore plus emmerdant, c'est si celui qui utilise la lib va également faire appel à un pipe() (par exemple) dans son prog.
Au début je m'étais dis, pour être MT-Safe, je n'utilise pas directement pipe() et cie, mais je créer des fonctions my_pipe(), etc,.. qui protègerait le vrai pipe() avec un mutex global pour tous les potentiels superviseurs. Mais ça ne règle le problème qu'à moitier. Vu que si celui qui utilise la lib parallélise également un pipe() en même temps que mes my_pipe().. mon mutex n'y changera rien.
Une possibilité serait d'exploiter l'argument -wrap du linker afin de wrapper toutes les fonctions qui posent problème à l'aide d'un
#include <pthread.h> #include <unistd.h> static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int __wrap_pipe (int fildes[2]) { int res; pthread_mutex_lock (&mutex); res = __real_pipe (fildes); pthread_mutex_unlock (&mutex); return res; }
Mais bon, je pense que vous serez d'accord avec moi que c'est débile.. je ne peux pas demander à l'utilisateur de la lib d'explicitement faire un `-wrap pipe` avec le linker..
Ca devrait être le job de la glibc!
Alors que faire? Il n'existe pas des fonctions équivalentes réentrantes ou mt-safe??
Hors ligne
En fait je suis surement un bouffon.. toutes ces fonctions sont Asnyc-Signal Safe (d'après les spécifications UNIX).. je dois avoir un bug ailleurs.. pourtant..
bizarre..
Hors ligne
Bon je laisse tomber, de toute façon même si ça marchait correctement ça impliquerait d'autres problèmes plus complexe ailleurs..
Et juste pour la forme et par rapport à mes recherches..
- Il semblerait que fork() endort tous les threads le temps de son exécution et est donc sûre.
- dup2() est atomique et ne peut donc pas bugger mais sans garanti qu'il réussi la duplication.. par contre le plus étrange c'est que je l'utilise uniquement via un sub-process et il échoue qu'en même. Il me retourne un "Bad file descriptor" 1 fois sur 10 dans une utilisations en parallèle. Je duplique en fait un descripteur dans le STDOUT_FILENO et STDERR_FILENO. Je suppose que le problème se situe à ce niveau là mais quelque chose m'échappe, je ne vois pas pourquoi 2 sub-process qui dupliqueraient dans le stdout/stderr en même temps peuvent échouer.
- pipe() semble ne jamais échouer.
- close() n'intervient pas vraiment dans le problème car ça merde avant son utilisation..
Hors ligne