shmget() renvoie SIGSEGV ?

Le
JKB
Bonjour à tous,

Petit problème du matin à vous soumettre. J'ai un bout de code qui
se comporte bizarrement (sous Linux amd64 et je n'ai pas les moyens
de tester ailleurs parce que ça joue avec la mémoire partagée et que
je ne veux pas tester ce genre de chose sur mes machines de prod).

Code :

nom contient un nom de fichier (avec son chemin). La TAILLE est
positive.

printf("Avant ftok");
clef = ftok(nom, 1);
printf("%p", clef);

if ((segment = shmget(clef, TAILLE,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1)
{
perror("ftok");
printf("Erreur !");
return;
}

printf("%s %d", nom, segment);
free(nom);

À l'exécution, j'obtiens un segmentation fault dans le shmget() :

Root cauchy:[/home/bertrand/rpl/build/src] > ./rpl -is
Init
Avant fopen (4)
Avant ftok
0x102a529
Erreur de segmentation

que le programme tourne en utilisateur ou en root. J'ai
naturellement vérifié avec ipcs que je n'explosais pas les
ressources allouées aux segments partagés.

Ce qui est surprenant, c'est que ce bout de code fonctionnait. Je
suppose qu'une ressource n'est pas libérée :

cauchy:[~/rpl/build/src] > ipcs -l

Shared Memory Limits --
max number of segments = 4096
max seg size (kbytes) = 327680
max total shared memory (kbytes) = 8388608
min seg size (bytes) = 1

Semaphore Limits --
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767

Messages: Limits --
max queues system wide = 7936
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384

cauchy:[~/rpl/build/src] > ipcs -u

Shared Memory Status --
segments allocated 20
pages allocated 11072 < ce n'est pas un peu haut ?
pages resident 2583
pages swapped 2098
Swap performance: 0 attempts 0 successes

Semaphore Status --
used arrays = 15
allocated semaphores = 127

Messages: Status --
allocated queues = 0
used headers = 0
used space = 0 bytes

cauchy:[~/rpl/build/src] >

J'ai essayé de libérer tout ce que je pouvais avec ipcrm sans
succès. Une idée ?

Cordialement,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse
=> http://grincheux.de-charybde-en-scylla.fr
Questions / Réponses high-tech
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Nicolas George
Le #22479081
JKB , dans le message écrit :
À l'exécution, j'obtiens un segmentation fault dans le shmget() :



Tu as essayé Valgrind ?
JKB
Le #22479191
Le 17 Aug 2010 08:58:54 GMT,
Nicolas George
JKB , dans le message écrit :
À l'exécution, j'obtiens un segmentation fault dans le shmget() :



Tu as essayé Valgrind ?



Naturellement. Valgrind me donne un plantage à un endroit aberrant
puisqu'il m'indique une ligne plus loin, sur une affectation
statique du style a = constante (avec un a tout ce qu'il y a de plus
valable). J'oubliais, les printf() sont chez moi _synchrones_, donc
s'il n'y a pas d'affichage, cela veut dire que le programme ne passe
pas dessus.

Nouvelle information : j'ai redémarré le poste et le résultat est le
même : segfault sans aucune indication.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Nicolas George
Le #22479231
JKB , dans le message écrit :
Naturellement. Valgrind me donne un plantage à un endroit aberrant
puisqu'il m'indique une ligne plus loin, sur une affectation
statique du style a = constante



Et absolument aucune erreur au dessus ?

Est-ce que tu pourrais élaguer ton code jusqu'à produire un exemple minimal
exhibant le phénomène ?
JKB
Le #22479281
Le 17 Aug 2010 09:31:59 GMT,
Nicolas George
JKB , dans le message écrit :
Naturellement. Valgrind me donne un plantage à un endroit aberrant
puisqu'il m'indique une ligne plus loin, sur une affectation
statique du style a = constante



Et absolument aucune erreur au dessus ?



Aucune erreur concernant la mémoire.

cauchy:[~/rpl/build/src] > valgrind ./rpl -is
1== Memcheck, a memory error detector
1== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
1== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
copyright info
1== Command: ./rpl -is
1==
Init
Avant fopen (4)
Avant ftok
0x102a01f
1== Use of uninitialised value of size 8
1== at 0x4C25812: __GI_strlen (mc_replace_strmem.c:284)
1== by 0x5D970C: librpl_transliterated_fprintf
(transliteration-conv.c:53)
1== by 0x5C727A: librpl_creation_fifos_signaux
(interruptions-conv.c:1871)
1== by 0x5CE9D8: librpl_rplinit (rpl-conv.c:252)
1== by 0x5DE75C: main (init-conv.c:29)
1==
1== Invalid read of size 1
1== at 0x4C25812: __GI_strlen (mc_replace_strmem.c:284)
1== by 0x5D970C: librpl_transliterated_fprintf
(transliteration-conv.c:53)
1== by 0x5C727A: librpl_creation_fifos_signaux
(interruptions-conv.c:1871)
1== by 0x5CE9D8: librpl_rplinit (rpl-conv.c:252)
1== by 0x5DE75C: main (init-conv.c:29)
1== Address 0x0 is not stack'd, malloc'd or (recently) free'd
1==
1==
1== Process terminating with default action of signal 11 (SIGSEGV)
1== Access not within mapped region at address 0x0
1== at 0x4C25812: __GI_strlen (mc_replace_strmem.c:284)
1== by 0x5D970C: librpl_transliterated_fprintf
(transliteration-conv.c:53)
1== by 0x5C727A: librpl_creation_fifos_signaux
(interruptions-conv.c:1871)
1== by 0x5CE9D8: librpl_rplinit (rpl-conv.c:252)
1== by 0x5DE75C: main (init-conv.c:29)

Le segment de mémoire est bien créé :
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x0102a01f 229377 bertrand 600 11440 0

Est-ce que tu pourrais élaguer ton code jusqu'à produire un exemple minimal
exhibant le phénomène ?



C'est un exemple minimal. C'est au tout début d'un programme.
Bizarrement, après avoir redémarré sous un autre noyau (2.6.35.2),
ça fonctionne. Ça ressemble donc à un bug du 2.6.33.3 utilisé
auparavant.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Nicolas George
Le #22479271
JKB , dans le message écrit :
1== Invalid read of size 1
1== at 0x4C25812: __GI_strlen (mc_replace_strmem.c:284)
1== by 0x5D970C: librpl_transliterated_fprintf
(transliteration-conv.c:53)
1== by 0x5C727A: librpl_creation_fifos_signaux
(interruptions-conv.c:1871)
1== by 0x5CE9D8: librpl_rplinit (rpl-conv.c:252)
1== by 0x5DE75C: main (init-conv.c:29)
1== Address 0x0 is not stack'd, malloc'd or (recently) free'd



Tu fais un printf(NULL), là.

C'est un exemple minimal.



Il n'est pas complet : je ne peux pas le copier-coller ici pour reproduire
et investiguer.

Bizarrement, après avoir redémarré sous un autre noyau (2.6.35.2),
ça fonctionne. Ça ressemble donc à un bug du 2.6.33.3 utilisé
auparavant.



J'ai des doutes. Le printf(NULL), en tout cas, doit être examiné de plus
près.
JKB
Le #22479321
Le 17 Aug 2010 09:58:35 GMT,
Nicolas George
JKB , dans le message écrit :
1== Invalid read of size 1
1== at 0x4C25812: __GI_strlen (mc_replace_strmem.c:284)
1== by 0x5D970C: librpl_transliterated_fprintf
(transliteration-conv.c:53)
1== by 0x5C727A: librpl_creation_fifos_signaux
(interruptions-conv.c:1871)
1== by 0x5CE9D8: librpl_rplinit (rpl-conv.c:252)
1== by 0x5DE75C: main (init-conv.c:29)
1== Address 0x0 is not stack'd, malloc'd or (recently) free'd



Tu fais un printf(NULL), là.



Non, j'en suis certain. Le seul printf() qui peut envoyer un NULL
est celui sur la variable 'nom' qui est correctement remplie.
Comment expliquerais-tu qu'en changeant juste de noyau, ça
fonctionne ?

C'est un exemple minimal.



Il n'est pas complet : je ne peux pas le copier-coller ici pour reproduire
et investiguer.



Certes, l'exemple minimal est chez moi.

Bizarrement, après avoir redémarré sous un autre noyau (2.6.35.2),
ça fonctionne. Ça ressemble donc à un bug du 2.6.33.3 utilisé
auparavant.



J'ai des doutes. Le printf(NULL), en tout cas, doit être examiné de plus
près.



JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Arnaud Giersch
Le #22479521
Mardi 17 août 2010, vers 10:53:35 (+0200), JKB a écrit:

clef = ftok(nom, 1);
printf("%pn", clef);


^^^^^^^^^^^^
clef, si de type key_t n'est pas un void* (64bits) mais un int (32 bits).

Arnaud
JKB
Le #22479511
Le Tue, 17 Aug 2010 13:19:09 +0200,
Arnaud Giersch
Mardi 17 août 2010, vers 10:53:35 (+0200), JKB a écrit:

clef = ftok(nom, 1);
printf("%pn", clef);


^^^^^^^^^^^^
clef, si de type key_t n'est pas un void* (64bits) mais un int (32 bits).



Exact.

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Nicolas George
Le #22479751
JKB , dans le message écrit :
Non, j'en suis certain. Le seul printf() qui peut envoyer un NULL
est celui sur la variable 'nom' qui est correctement remplie.



Je lis la sortie de ton valgrind : tu as un strlen(NULL) appelé depuis
librpl_transliterated_fprintf, tu n'en sors pas.

Comment expliquerais-tu qu'en changeant juste de noyau, ça
fonctionne ?



Aucune idée, mais c'est très audacieux de considérer que le cas où ça marche
est le cas normal, et le cas où ça segfaulte le cas exceptionnel lié à un
bug du noyau.

Certes, l'exemple minimal est chez moi.



Dans ce cas, on est très limité dans l'aide qu'on peut t'apporter.
JKB
Le #22479841
Le 17 Aug 2010 12:30:33 GMT,
Nicolas George
JKB , dans le message écrit :
Non, j'en suis certain. Le seul printf() qui peut envoyer un NULL
est celui sur la variable 'nom' qui est correctement remplie.



Je lis la sortie de ton valgrind : tu as un strlen(NULL) appelé depuis
librpl_transliterated_fprintf, tu n'en sors pas.



Et moi, je te dis que ce n'est _pas_ possible pour la simple raison
que cette fonction prend juste l'argument du printf pour la balancer
à une autre routine de sortie lorsque le programme a achevé son
initialisation. Dans mon cas, cette fonction est totalement
transparente. Le fait qu'il y ait quelque part un strlen(NULL) n'est
pas dû à mon programme, en tout cas, pas à ce que j'ai écrit. De toute
façon, ça plante _avant_ l'appel à cette fonction, et il y a une
corruption de la pile quelque part. Si tu laissais le programme faire
un core pour une analyse post-mortem, tu tombais sur une autre erreur
sur la ligne :

(*s_etat_processus).erreur_systeme = d_es_allocation_memoire;

que j'ai viré du bout de programme que j'ai posté ici tellement
cette erreur était aberrante !

s_etat_processus est allouée et d_es_allocation_memoire est une
constante définie dans un #define. Il n'y a donc aucune raison pour
que cette ligne fasse un segfault, et pourtant, c'est bien ce que
valgrind reporte !

Au passage, avant de poser la question ici, j'ai cherché l'origine
du problème durant quelques heures et j'étais tombé sur la même
chose que toi, ce qui est un diagnostic idiot vu le programme.

Il ne faut pas perdre de vue que l'information issue de backtrace()
part du principe que la pile n'a pas été corrompue et tu n'as aucune
certitude sur ce point.

Comment expliquerais-tu qu'en changeant juste de noyau, ça
fonctionne ?



Aucune idée, mais c'est très audacieux de considérer que le cas où ça marche
est le cas normal, et le cas où ça segfaulte le cas exceptionnel lié à un
bug du noyau.



Tu n'as aucune idée du nombre de bugs à la turc que j'ai déjà trouvé
dans des coins obscurs des différents Unix sur lesquels je bosse (et
en particulier dans la glibc lorsque le noyau n'est pas de la bonne
version).

Maintenant, je repose ma question : comment expliques-tu qu'avec un
2.6.33, ça explose et qu'avec tous les autres Unix (y compris Linux
avec un noyau plus récent), ça passe sans aucun souci. Ni valgrind,
ni purify ni aucun autre outil ne trouve des choses à redire.

Certes, l'exemple minimal est chez moi.



Dans ce cas, on est très limité dans l'aide qu'on peut t'apporter.



La question initiale portait autour d'un segfault _dans_ shmget().
Problème réglé.

Merci pour ton intérêt au sujet,

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Publicité
Poster une réponse
Anonyme