Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

C, Mac OS X et sem_open

13 réponses
Avatar
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\n", 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.

10 réponses

1 2
Avatar
Éric Lévénez
Bonjour,

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 : <http://www.levenez.com/lang/c/faq/>
Avatar
JKB
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,
Éric Lévénez ?crivait dans fr.comp.lang.c :
Bonjour,

Comme beaucoup de personnes tu confonds Mac OS et Mac OS X qui sont deux
systèmes d'exploitation différents.



Il me semble pourtant avoir écrit Mac OS X. Passons...

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];



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.

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.



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 <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

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.

Remarque finale : le C c'est pas du LISP... :-)



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.
Avatar
Bruno Ducrot
On 2010-04-16, JKB wrote:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

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);
}




Comme on peut le lire ici :

http://lists.apple.com/archives/unix-porting/2003/Feb/msg00133.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.
Avatar
JKB
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,
Bruno Ducrot ?crivait dans fr.comp.lang.c :
On 2010-04-16, JKB wrote:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

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);
}




Comme on peut le lire ici :

http://lists.apple.com/archives/unix-porting/2003/Feb/msg00133.html

MacOS X renvoie un file descriptor lors d'un appel a sem_open(), meme si
celui-ci est deguise en pointeur.



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 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.



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.
Avatar
Éric Lévénez
Le 16/04/10 18:28, JKB a écrit :
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,

Je ne saurais te dire si cela casse une quelconque prescription dans
Posix.





Mac OS X 10.5 et 10.6 sont Posix car UNIX.

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.





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...

Je vais continuer à réfléchir là dessus...



Voilà :-)

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
JKB
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,
Éric Lévénez ?crivait dans fr.comp.lang.c :
Le 16/04/10 18:28, JKB a écrit :
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,



Je ne saurais te dire si cela casse une quelconque prescription dans
Posix.





Mac OS X 10.5 et 10.6 sont Posix car UNIX.



Non. Ils ne sont Posix qu'en partie (et je connais des Unix pas
Posix pour un sou). D'ailleurs, s'ils étaient parfaitement Posix,
mon problème n'existerait pas.

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.





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...

Je vais continuer à réfléchir là dessus...



Voilà :-)



Et ce n'est pas simple...

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.
Avatar
Éric Lévénez
Le 16/04/10 22:33, JKB a écrit :

Mac OS X 10.5 et 10.6 sont Posix car UNIX.



Non. Ils ne sont Posix qu'en partie (et je connais des Unix pas
Posix pour un sou). D'ailleurs, s'ils étaient parfaitement Posix,
mon problème n'existerait pas.



Relis les spés des sémaphores dans Posix. Il n'est pas dit que l'on
puisse utiliser le pointeur pour regarder là où il pointe. C'est une
valeur opaque. D'ailleurs pour regarder où ça pointerait il faudrait
connaître au moins un élément de la supposée structure. Et que dit la
norme Posix ? Rien bien sûr puisque que c'est un élément opaque. Rien à
voir, allez circulez !

De plus ton code n'a pas besoin de cela pour affecter la valeur du
pointeur à une variable, qu'il vaille 0x3 ou 0xbec04254. C'est en te
trompant, en partie à cause de toutes ces parenthèses, sur les
indirections que tu as essayé d'aller à l'adresse pointée.

J'espère que tu ne fais pas la même chose avec FILE... Il y a bien
longtemps on bidouillait directement dans la structure FILE, maintenant
personne ne fait cela. On a une valeur de pointeur, et on l'utilise dans
des appels de fonctions, que la valeur vaille 0x3 ou 0xbec04254.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
JKB
Le 16-04-2010, ? propos de
Re: C, Mac OS X et sem_open,
Éric Lévénez ?crivait dans fr.comp.lang.c :
Le 16/04/10 22:33, JKB a écrit :

Mac OS X 10.5 et 10.6 sont Posix car UNIX.



Non. Ils ne sont Posix qu'en partie (et je connais des Unix pas
Posix pour un sou). D'ailleurs, s'ils étaient parfaitement Posix,
mon problème n'existerait pas.



Relis les spés des sémaphores dans Posix. Il n'est pas dit que l'on
puisse utiliser le pointeur pour regarder là où il pointe. C'est une
valeur opaque. D'ailleurs pour regarder où ça pointerait il faudrait
connaître au moins un élément de la supposée structure. Et que dit la
norme Posix ? Rien bien sûr puisque que c'est un élément opaque. Rien à
voir, allez circulez !



Oui, sauf que tu oublies une contrainte. Convertir le plus
facilement un truc utilisant sem_init() en machin utilisant
sem_open(). Et là, ça coince parce que sem_init() peut s'utiliser
avec un sem_t tout ce qu'il y a de plus statique :

sem_t semaphore;
sem_init(&semaphore, 1);

alors que dans le cas sem_open(), c'est parfaitement impossible.

De plus ton code n'a pas besoin de cela pour affecter la valeur du
pointeur à une variable, qu'il vaille 0x3 ou 0xbec04254. C'est en te
trompant, en partie à cause de toutes ces parenthèses, sur les
indirections que tu as essayé d'aller à l'adresse pointée.



Là, je ne suis plus d'accord. Mon code est valable à partir du
moment où le sem_t * pointe sur quelque chose. Dans tous les Unix
testés (sauf Mac OS X), c'est vrai. Dans le cas Mac OS X, c'est faux
parce que le sem_t * est un entier qui n'a aucune raison de pointer
sur quelque chose de valable. Je commence même à comprendre pourquoi
il n'y a pas de sémaphores anonymes sous Mac OS X parce que le fait
d'utiliser un int pour une sem_t *, ça casse l'interface de
sem_init().

J'espère que tu ne fais pas la même chose avec FILE... Il y a bien
longtemps on bidouillait directement dans la structure FILE, maintenant
personne ne fait cela. On a une valeur de pointeur, et on l'utilise dans
des appels de fonctions, que la valeur vaille 0x3 ou 0xbec04254.



Je ne fais _jamais_ ça (sauf contraint et forcé). Là, je suis
simplement parti pour corriger un truc de plusieurs centaines de
milliers de lignes à grands coups de #ifdef. Si j'avais pu éviter,
ça m'aurait éviter quelques jours de boulot bien insipides.

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.
Avatar
Éric Lévénez
Le 17/04/10 09:46, JKB a écrit :

Oui, sauf que tu oublies une contrainte. Convertir le plus
facilement un truc utilisant sem_init() en machin utilisant
sem_open(). Et là, ça coince parce que sem_init() peut s'utiliser
avec un sem_t tout ce qu'il y a de plus statique :

sem_t semaphore;
sem_init(&semaphore, 1);

alors que dans le cas sem_open(), c'est parfaitement impossible.




Oui effectivement, mais comme Mac OS X ne supporte pas sem_open,
sem_destroy, sem_getvalue (voir
<http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/posix_sem.c>)
il n'y a pas de problème. :-) Pour avoir les sémaphores anonymes, Mac OS
X devra modifier son interface. Le projet Darwin étant public, tout le
monde peut changer cela. Mais comme cela fait bien des années que cela
n'a pas évolué (à part une couche de sécurité déployée), il semble que
ce n'est pas prêt de changer.

Là, je ne suis plus d'accord. Mon code est valable à partir du
moment où le sem_t * pointe sur quelque chose. Dans tous les Unix
testés (sauf Mac OS X), c'est vrai. Dans le cas Mac OS X, c'est faux
parce que le sem_t * est un entier qui n'a aucune raison de pointer
sur quelque chose de valable. Je commence même à comprendre pourquoi
il n'y a pas de sémaphores anonymes sous Mac OS X parce que le fait
d'utiliser un int pour une sem_t *, ça casse l'interface de
sem_init().



Je ne sais pas si c'est la seule raison, mais c'est une raison
suffisante pour le moment. Le véritable problème je pense vient de Mach
qui n'a pas ces sémaphores et comme les sémaphores Posix sont mappés sur
les sémaphores Mach
<http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/osfmk/kern/sync_sema.c>...

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
JKB
Le 17-04-2010, ? propos de
Re: C, Mac OS X et sem_open,
Éric Lévénez ?crivait dans fr.comp.lang.c :
Le 17/04/10 09:46, JKB a écrit :

Oui, sauf que tu oublies une contrainte. Convertir le plus
facilement un truc utilisant sem_init() en machin utilisant
sem_open(). Et là, ça coince parce que sem_init() peut s'utiliser
avec un sem_t tout ce qu'il y a de plus statique :

sem_t semaphore;
sem_init(&semaphore, 1);

alors que dans le cas sem_open(), c'est parfaitement impossible.




Oui effectivement, mais comme Mac OS X ne supporte pas sem_open,
sem_destroy, sem_getvalue (voir
<http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/posix_sem.c>)
il n'y a pas de problème. :-) Pour avoir les sémaphores anonymes, Mac OS
X devra modifier son interface. Le projet Darwin étant public, tout le
monde peut changer cela. Mais comme cela fait bien des années que cela
n'a pas évolué (à part une couche de sécurité déployée), il semble que
ce n'est pas prêt de changer.

Là, je ne suis plus d'accord. Mon code est valable à partir du
moment où le sem_t * pointe sur quelque chose. Dans tous les Unix
testés (sauf Mac OS X), c'est vrai. Dans le cas Mac OS X, c'est faux
parce que le sem_t * est un entier qui n'a aucune raison de pointer
sur quelque chose de valable. Je commence même à comprendre pourquoi
il n'y a pas de sémaphores anonymes sous Mac OS X parce que le fait
d'utiliser un int pour une sem_t *, ça casse l'interface de
sem_init().



Je ne sais pas si c'est la seule raison, mais c'est une raison
suffisante pour le moment. Le véritable problème je pense vient de Mach
qui n'a pas ces sémaphores et comme les sémaphores Posix sont mappés sur
les sémaphores Mach
<http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/osfmk/kern/sync_sema.c>...



Certes. Mais je n'ai toujours pas trouvé la raison valable pour
laquelle sem_getvalue() n'existe pas.

JKB, qui va émuler un sem_getvalue() à grands coups de sem_trywait()
et de mutexes...

--
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.
1 2