C, Mac OS X et sem_open
Le
JKB
Bonjour à tous,
Je viens d'écrire une verrue à grands coups de #define dans un
programme pour le faire fonctionner sous Mac OS. Mac OS ne connaît
pas les sémaphores anonymes et j'ai bricolé le code suivant pour que
ça passe. Ce n'est pas très propre mais ça fonctionne parfaitement
sous Linux. Sous Mac OS, ça plante bizarrement. Par acquis de
conscience, j'ai passé le truc dans valgrind sans aucune alerte et
j'ai essayé sous NetBSD et sous Solaris. Ça fonctionne correctement
sur tous mes OS de test _sauf_ sur Mac OS. J'avoue de pas trop
comprendre.
Lorsque je veux compiler sous Mac OS (ou sur les autres OS en
émulation), je définis la macro suivante. Il va sans dire que les
variables noms_semaphores et semaphores_nommes sont définies en
variables globales :
unsigned char noms_semaphores[4][64];
sem_t *semaphores_nommes[4];
inline int
sem_open2(sem_t *sem, const char *name, int oflags, int options,
unsigned int value, int semaphore)
{
semaphores_nommes[semaphore] = sem_open(name, oflags, options, value);
printf("%p %p", SEM_FAILED, semaphores_nommes[semaphore]);
if (semaphores_nommes[semaphore] == SEM_FAILED)
{
return(-1);
}
(*sem) = (*(semaphores_nommes[semaphore]));
return(0);
}
# define sem_init(sem_ptr, pshared, value) \
({ \
int semaphore; \
int longueur; \
if (strcmp(#sem_ptr, "&semaphore_liste_threads") == 0) \
semaphore = 0; \
else if (strcmp(#sem_ptr, "&semaphore_gestionnaires_signaux") == 0) \
semaphore = 1; \
else if (strcmp(#sem_ptr, "&semaphore_gestionnaires_signaux_atomique") \
== 0) \
semaphore = 2; \
else \
semaphore = 3; \
longueur = snprintf(noms_semaphores[semaphore], 64, \
"/RPLSEM-%d-%llu-%d", getpid(), \
(unsigned long long) pthread_self(), semaphore); \
sem_open2(sem_ptr, noms_semaphores[semaphore], O_CREAT, \
(S_IRUSR | S_IWUSR), value, semaphore); \
})
À l'exécution et avec MacOS, ça donne :
0xffffffff 0x3
Bus error
gdb me renvoit en plus :
EXC_BAD_ACCESS, Could not access memory
Reason: KERN_PROTECTION_FAILURE at address: 0x00000003
(*sem) = (*(semaphores_nommes[semaphore]));
print semaphores_nommes
$1 = { 0x3, 0x0, 0x0, 0x0 }
J'ai essayé memcpy à la place de l'affectation brutale, mais ça ne
change rien au problème.
La question est donc : pourquoi sem_open() renvoit-il 0x3 ?
J'oubliais, le Mac OS X en question est un 10.5.6 x86.
Merci de vos lumières,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Je viens d'écrire une verrue à grands coups de #define dans un
programme pour le faire fonctionner sous Mac OS. Mac OS ne connaît
pas les sémaphores anonymes et j'ai bricolé le code suivant pour que
ça passe. Ce n'est pas très propre mais ça fonctionne parfaitement
sous Linux. Sous Mac OS, ça plante bizarrement. Par acquis de
conscience, j'ai passé le truc dans valgrind sans aucune alerte et
j'ai essayé sous NetBSD et sous Solaris. Ça fonctionne correctement
sur tous mes OS de test _sauf_ sur Mac OS. J'avoue de pas trop
comprendre.
Lorsque je veux compiler sous Mac OS (ou sur les autres OS en
émulation), je définis la macro suivante. Il va sans dire que les
variables noms_semaphores et semaphores_nommes sont définies en
variables globales :
unsigned char noms_semaphores[4][64];
sem_t *semaphores_nommes[4];
inline int
sem_open2(sem_t *sem, const char *name, int oflags, int options,
unsigned int value, int semaphore)
{
semaphores_nommes[semaphore] = sem_open(name, oflags, options, value);
printf("%p %p", SEM_FAILED, semaphores_nommes[semaphore]);
if (semaphores_nommes[semaphore] == SEM_FAILED)
{
return(-1);
}
(*sem) = (*(semaphores_nommes[semaphore]));
return(0);
}
# define sem_init(sem_ptr, pshared, value) \
({ \
int semaphore; \
int longueur; \
if (strcmp(#sem_ptr, "&semaphore_liste_threads") == 0) \
semaphore = 0; \
else if (strcmp(#sem_ptr, "&semaphore_gestionnaires_signaux") == 0) \
semaphore = 1; \
else if (strcmp(#sem_ptr, "&semaphore_gestionnaires_signaux_atomique") \
== 0) \
semaphore = 2; \
else \
semaphore = 3; \
longueur = snprintf(noms_semaphores[semaphore], 64, \
"/RPLSEM-%d-%llu-%d", getpid(), \
(unsigned long long) pthread_self(), semaphore); \
sem_open2(sem_ptr, noms_semaphores[semaphore], O_CREAT, \
(S_IRUSR | S_IWUSR), value, semaphore); \
})
À l'exécution et avec MacOS, ça donne :
0xffffffff 0x3
Bus error
gdb me renvoit en plus :
EXC_BAD_ACCESS, Could not access memory
Reason: KERN_PROTECTION_FAILURE at address: 0x00000003
(*sem) = (*(semaphores_nommes[semaphore]));
print semaphores_nommes
$1 = { 0x3, 0x0, 0x0, 0x0 }
J'ai essayé memcpy à la place de l'affectation brutale, mais ça ne
change rien au problème.
La question est donc : pourquoi sem_open() renvoit-il 0x3 ?
J'oubliais, le Mac OS X en question est un 10.5.6 x86.
Merci de vos lumières,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.

Poser une question


Comme beaucoup de personnes tu confonds Mac OS et Mac OS X qui sont deux
systèmes d'exploitation différents. Ton problème actuel est, si je ne
m'abuse, uniquement sur du traitement de tableau de pointeurs, et pas
sur un de ces systèmes.
Comme le code que tu as posté est un petit fragment, avec des macros non
utilisés, des conditions d'entrée non défini, et aucun commentaire, ce
n'est pas simple de t'aider.
Fait un tout petit programme avec un main, qui compile, et poste le code
ici. Peut-être même qu'en faisant cela tu trouveras le problème.
Petites remarques : au lieu d'un gros define tout pourri, tu devrais
faire une fonction inline. Au lieu d'utiliser des constantes comme 64,
du devrait utiliser un define, ou mieux faire un sizeof idoine. Au lieu
de supposer que getpid retourne un int du devrait caster son résultat
pour le snprintf.
Enfin bref, le :
sem_t *sem;
(*sem) = (*(semaphores_nommes[semaphore]));
sem_open2(sem_ptr, ...);
Ne devrait-il pas être un truc du genre :
sem_t **sem;
*sem = semaphores_nommes[semaphore];
Car ton tableau de sémaphores est un tableau de 4 pointeurs, et tu
essaies d'accéder à la valeur pointée, et pointeur valant 3 (vu par le
printf), cela part en erreur (pas de mémoire en 0x3), bien sûr.
Remarque finale : le C c'est pas du LISP... :-)
--
Éric Lévénez
FAQ de fclc :
Re: C, Mac OS X et sem_open,
Éric Lévénez ?crivait dans fr.comp.lang.c :
Il me semble pourtant avoir écrit Mac OS X. Passons...
Il y a une contrainte. Ça doit fonctionner aussi sur un système
gérant les sémaphores anonymes. Les appels sont du type
sem_init(&variable) et l'esperluette pose un tas de problèmes.
Bon, on va reprendre le problème à la base :
semaphores_nommes est un tableau de quatre pointeurs sur des sem_t.
En écrivant :
semaphores_nommes[semaphore] = sem_open(name, oflags, options, value);
je récupère le pointeur sur le sémaphore créé. Dans mon exemple,
semaphore vaut 0.
semaphores_nommes[0] doit donc contenir un pointeur sur ce sémaphore
et une adresse accessible.
Avant de poster, j'ai tourné le problème depuis hier matin sans
succès. Je suis conscient que le bout de code n'est pas vraiment
propre, mais c'est juste une rustine pour ne pas casser un gros bout
de code qui fonctionne partout ailleurs. Et j'ai un exemple minimal
sous la main :
#include #include #include
int
main()
{
sem_t *s;
s = sem_open("/test", O_CREAT, S_IRUSR | S_IWUSR, 1);
printf("%pn", s);
sem_close(s);
sem_unlink("/test");
return(0);
}
Plus simple, je ne sais pas faire...
Résultat des courses :
Mac OS X (10.5.6) renvoie une valeur à la noix (Xcode 3.1.4 et gcc 4.0) :
0x3
Linux sparc, Solaris sparc, NetBSD renvoient tous une valeur correcte :
0xf7ec8000 (linux/sparc)
Je ne vois toujours pas le problème.
Ce n'est pas aux vieux singes qu'on apprend à faire des grimaces ;-)
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Comme on peut le lire ici :
http://lists.apple.com/archives/uni...00133.html
MacOS X renvoie un file descriptor lors d'un appel a sem_open(), meme si
celui-ci est deguise en pointeur.
Je ne saurais te dire si cela casse une quelconque prescription dans
Posix. En tout cas, je ne vois pas de raisons particulieres pour que ce
ne soit pas permis, et l'on devrait considerer qu'un sem_t * est un truc
completement opaque, dont la copie, par exemple, ne peut servir a rien.
Un peu comme un FILE *, quoi.
A plus,
--
Bruno Ducrot
-- Which is worse: ignorance or apathy?
-- Don't know. Don't care.
Re: C, Mac OS X et sem_open,
Bruno Ducrot ?crivait dans fr.comp.lang.c :
Dans les en-têtes, j'ai un "typedef sem_t int", ce qui me ferait
plutôt penser que le prototype de sem_open est sem_t semopen()
plutôt que sem_t *sem_open().
Je vais continuer à réfléchir là dessus...
Cordialement,
JKB
--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Mac OS X 10.5 et 10.6 sont Posix car UNIX.
C'est exactement cela. Et la conséquence est que ceux qui vont
trifouiller dans ces structures opaques ont un jour ou l'autre un
problème de portabilité.
Donc : Pas joujou avec "sem_t *". On le stocke et on l'utilise quand on
en a besoin, on essaye pas de regarder ce qu'il y a dedans vu qu'il n'y
a pas toujours un dedans...
Voilà :-)
--
Éric Lévénez
FAQ de fclc :