J'ai un petit doute sur la gestion des signaux POSIX installés grâce
à sigaction(). J'ai accès à un certain nombre d'Unix dont Linux,
Tru64, Solaris, NetBSD, OpenBSD et FreeBSD. Et NetBSD me pose un
petit problème. Je n'arrive pas à savoir s'il s'agit d'un problème
dans mon code ou d'u truc qui m'aurait échappé.
Considérons le code suivant :
do
{
code_retour = nanosleep(&temporisation, &temporisation);
erreur = errno;
Je simplifie. J'interromps nanosleep() grâce à un SIGINT (ctrl+C) et
je vois le gestionnaire se lancer (j'ai collé un printf() dans le
gestionnaire en question). Sous NetBSD, le gestionnaire de signal
est lancé dans un thread spécifique (et non le thread de
l'appelant). Ça ne semble pas être en contradiction avec les specs
POSIX. Mais nanosleep() sort avec un code d'erreur EINTR _avant_ que
le signal soit effectivement traité. Or dans la suite des
instructions de la boucle se trouve un test sur une variable volatile
et atomique positionnée par ce gestionnaire de signal. La plupart du
temps, ce test échoue car le gestionnaire de signal s'exécutant dans
un autre thread n'a pas encore positionné la variable à la bonne
valeur.
D'où une série de questions ;-)
1/ Est-ce un comportement attendu ou un bug de la gestion des
signaux de NetBSD ? Je n'observe ce comportement que sous ce
système.
2/ Comment s'assurer de façon propre que le gestionnaire de signal
a terminé ses traitement sans y coller un sem_post() (j'aimerais
éviter) ?
Merci de votre attention,
JKB
PS: Nicolas George, pas la peine de répondre, je t'ai plonké depuis
longtemps.
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Utiliser une variable ne serait possible qu'en utilisant les variables globales par thread, mais ces fonctions ne peuvent pas être appelées depuis un gestionnaire de signal...
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé... Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs à la manière des PID, sous Linux, il s'agit de pointeurs (sans vérification, ce qui fait qu'un pthread_kill() sur un thread inexistant ne retourne pas une erreur mais un segfault :-( ). Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Mais merci pour la suggestion.
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
Le Thu, 11 Oct 2012 14:12:55 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Le 11 octobre 2012, JKB a écrit :
Utiliser une variable ne serait possible qu'en utilisant les
variables globales par thread, mais ces fonctions ne peuvent pas
être appelées depuis un gestionnaire de signal...
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que
le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs
à la manière des PID, sous Linux, il s'agit de pointeurs (sans
vérification, ce qui fait qu'un pthread_kill() sur un thread
inexistant ne retourne pas une erreur mais un segfault :-( ).
Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Mais merci pour la suggestion.
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
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Utiliser une variable ne serait possible qu'en utilisant les variables globales par thread, mais ces fonctions ne peuvent pas être appelées depuis un gestionnaire de signal...
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé... Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs à la manière des PID, sous Linux, il s'agit de pointeurs (sans vérification, ce qui fait qu'un pthread_kill() sur un thread inexistant ne retourne pas une erreur mais un segfault :-( ). Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Mais merci pour la suggestion.
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
Bruno Ducrot
On 08-10-2012, JKB wrote:
2/ Comment s'assurer de façon propre que le gestionnaire de signal a terminé ses traitement sans y coller un sem_post() (j'aimerais éviter) ?
Un truc bien crade, genre setcontext((ucontext_t*) context) à la fin du handler, ca ne pourrait pas le faire ?
-- Bruno Ducrot
A quoi ca sert que Ducrot hisse des carcasses ?
On 08-10-2012, JKB wrote:
2/ Comment s'assurer de façon propre que le gestionnaire de signal
a terminé ses traitement sans y coller un sem_post() (j'aimerais
éviter) ?
Un truc bien crade, genre setcontext((ucontext_t*) context) à la fin
du handler, ca ne pourrait pas le faire ?
Le 11 Oct 2012 14:01:14 GMT, Bruno Ducrot écrivait :
On 08-10-2012, JKB wrote:
2/ Comment s'assurer de façon propre que le gestionnaire de signal a terminé ses traitement sans y coller un sem_post() (j'aimerais éviter) ?
Un truc bien crade, genre setcontext((ucontext_t*) context) à la fin du handler, ca ne pourrait pas le faire ?
Dans un gestionnaire de signal ? Je ne m'y risquerais pas ;-)
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
Lucas Levrel
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs à la manière des PID, sous Linux, il s'agit de pointeurs (sans vérification, ce qui fait qu'un pthread_kill() sur un thread inexistant ne retourne pas une erreur mais un segfault :-( ). Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Mais merci pour la suggestion.
Merci de me supporter :-)
-- LL
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que
le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera
son index dans le tableau, non ?
Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs
à la manière des PID, sous Linux, il s'agit de pointeurs (sans
vérification, ce qui fait qu'un pthread_kill() sur un thread
inexistant ne retourne pas une erreur mais un segfault :-( ).
Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Par ailleurs, si sous Solaris, les TID sont des entiers consécutifs à la manière des PID, sous Linux, il s'agit de pointeurs (sans vérification, ce qui fait qu'un pthread_kill() sur un thread inexistant ne retourne pas une erreur mais un segfault :-( ). Difficile d'en faire un tableau. Tout au plus une liste chaînée.
Mais merci pour la suggestion.
Merci de me supporter :-)
-- LL
JKB
Le Thu, 11 Oct 2012 17:40:14 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Oui, mais aprè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
Le Thu, 11 Oct 2012 17:40:14 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que
le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera
son index dans le tableau, non ?
Oui, mais aprè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
When a signal handler is executed, the current user context is saved and a new context is created. If the thread leaves the signal handler via longjmp(), then it is unspecified whether the context at the time of the corresponding setjmp() call is restored and thus whether future calls to getcontext() will provide an accurate representation of the current context, since the context restored by longjmp() does not necessarily contain all the information that setcontext() requires. Signal handlers should use siglongjmp() or setcontext() instead. </cite>
When a signal handler is executed, the current user context is
saved and a new context is created. If the thread leaves the signal
handler via longjmp(), then it is unspecified whether the context
at the time of the corresponding setjmp() call is restored and thus
whether future calls to getcontext() will provide an accurate representation
of the current context, since the context restored by longjmp() does
not necessarily contain all the information that setcontext() requires.
Signal handlers should use siglongjmp() or setcontext() instead.
</cite>
When a signal handler is executed, the current user context is saved and a new context is created. If the thread leaves the signal handler via longjmp(), then it is unspecified whether the context at the time of the corresponding setjmp() call is restored and thus whether future calls to getcontext() will provide an accurate representation of the current context, since the context restored by longjmp() does not necessarily contain all the information that setcontext() requires. Signal handlers should use siglongjmp() or setcontext() instead. </cite>
When a signal handler is executed, the current user context is saved and a new context is created. If the thread leaves the signal handler via longjmp(), then it is unspecified whether the context at the time of the corresponding setjmp() call is restored and thus whether future calls to getcontext() will provide an accurate representation of the current context, since the context restored by longjmp() does not necessarily contain all the information that setcontext() requires. Signal handlers should use siglongjmp() or setcontext() instead. </cite>
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller dans un gestionnaire de signal...
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
Le 12 Oct 2012 09:35:22 GMT,
Bruno Ducrot <ducrot@echo.fr> écrivait :
On 11-10-2012, JKB wrote:
Le 11 Oct 2012 14:01:14 GMT,
Bruno Ducrot <ducrot@echo.fr> écrivait :
On 08-10-2012, JKB wrote:
2/ Comment s'assurer de façon propre que le gestionnaire de signal
a terminé ses traitement sans y coller un sem_post() (j'aimerais
éviter) ?
Un truc bien crade, genre setcontext((ucontext_t*) context) à la fin
du handler, ca ne pourrait pas le faire ?
Dans un gestionnaire de signal ? Je ne m'y risquerais pas ;-)
When a signal handler is executed, the current user context is
saved and a new context is created. If the thread leaves the signal
handler via longjmp(), then it is unspecified whether the context
at the time of the corresponding setjmp() call is restored and thus
whether future calls to getcontext() will provide an accurate representation
of the current context, since the context restored by longjmp() does
not necessarily contain all the information that setcontext() requires.
Signal handlers should use siglongjmp() or setcontext() instead.
</cite>
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal
safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller
dans un gestionnaire de signal...
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
When a signal handler is executed, the current user context is saved and a new context is created. If the thread leaves the signal handler via longjmp(), then it is unspecified whether the context at the time of the corresponding setjmp() call is restored and thus whether future calls to getcontext() will provide an accurate representation of the current context, since the context restored by longjmp() does not necessarily contain all the information that setcontext() requires. Signal handlers should use siglongjmp() or setcontext() instead. </cite>
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller dans un gestionnaire de signal...
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
Lucas Levrel
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 17:40:14 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant « maison » et récupère son pointeur (1er argument de pthread_create) ; il met alors la paire identifiant-pointeur dans le tableau global. Le gestionnaire et les threads ont alors accès aux pointeurs de tous les threads sur la base de leur identifiant. Mais il est peut-être impossible de lire le tableau de façon async-signal-safe ?
-- LL
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 17:40:14 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que
le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera
son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que
l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant
« maison » et récupère son pointeur (1er argument de pthread_create) ; il
met alors la paire identifiant-pointeur dans le tableau global. Le
gestionnaire et les threads ont alors accès aux pointeurs de tous les
threads sur la base de leur identifiant. Mais il est peut-être impossible
de lire le tableau de façon async-signal-safe ?
Le Thu, 11 Oct 2012 17:40:14 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant « maison » et récupère son pointeur (1er argument de pthread_create) ; il met alors la paire identifiant-pointeur dans le tableau global. Le gestionnaire et les threads ont alors accès aux pointeurs de tous les threads sur la base de leur identifiant. Mais il est peut-être impossible de lire le tableau de façon async-signal-safe ?
-- LL
JKB
Le Fri, 12 Oct 2012 12:17:41 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 17:40:14 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant « maison » et récupère son pointeur (1er argument de pthread_create) ; il met alors la paire identifiant-pointeur dans le tableau global. Le gestionnaire et les threads ont alors accès aux pointeurs de tous les threads sur la base de leur identifiant. Mais il est peut-être impossible de lire le tableau de façon async-signal-safe ?
Ce que je ne vois pas (mais je dois rater un truc dans ton raisonnement). Dans ton gestionnaire de signal, tu as donc un tableau comportant une association entre un ID 'maison' et le TID. Tu ne peux utiliser pthread_self(), mais comment connais-tu dans le gestionnaire l'ID 'maison' ? Tu ne peux le connaître que grâce à une variable globale au thread et ces fonctions ne sont pas async sygnal safe.
Ou je n'ai pas compris...
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
Le Fri, 12 Oct 2012 12:17:41 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 17:40:14 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200,
Lucas Levrel <lucas.levrel@u-pec.fr> écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que
le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera
son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que
l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant
« maison » et récupère son pointeur (1er argument de pthread_create) ; il
met alors la paire identifiant-pointeur dans le tableau global. Le
gestionnaire et les threads ont alors accès aux pointeurs de tous les
threads sur la base de leur identifiant. Mais il est peut-être impossible
de lire le tableau de façon async-signal-safe ?
Ce que je ne vois pas (mais je dois rater un truc dans ton
raisonnement). Dans ton gestionnaire de signal, tu as donc un
tableau comportant une association entre un ID 'maison' et le TID.
Tu ne peux utiliser pthread_self(), mais comment connais-tu dans le
gestionnaire l'ID 'maison' ? Tu ne peux le connaître que grâce à une
variable globale au thread et ces fonctions ne sont pas async sygnal
safe.
Ou je n'ai pas compris...
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
Le Fri, 12 Oct 2012 12:17:41 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 17:40:14 +0200, Lucas Levrel écrivait :
Le 11 octobre 2012, JKB a écrit :
Le Thu, 11 Oct 2012 14:12:55 +0200, Lucas Levrel écrivait :
Et un « bête » tableau global (à chaque thread sa case) ? Je suppose que le nombre de threads est variable... Une liste chaînée ?
pthread_self() n'est pas async signal safe. J'y avais déjà pensé...
Mais quand tu crées un thread, tu peux lui passer un identifiant qui sera son index dans le tableau, non ?
Oui, mais après ?
Eh bien je ne vois pas pourquoi tu as besoin de pthread_self. Est-ce que l'identifiant « maison » ne suffit pas ?
Sinon, quand un thread est créé, le créateur lui passe un identifiant « maison » et récupère son pointeur (1er argument de pthread_create) ; il met alors la paire identifiant-pointeur dans le tableau global. Le gestionnaire et les threads ont alors accès aux pointeurs de tous les threads sur la base de leur identifiant. Mais il est peut-être impossible de lire le tableau de façon async-signal-safe ?
Ce que je ne vois pas (mais je dois rater un truc dans ton raisonnement). Dans ton gestionnaire de signal, tu as donc un tableau comportant une association entre un ID 'maison' et le TID. Tu ne peux utiliser pthread_self(), mais comment connais-tu dans le gestionnaire l'ID 'maison' ? Tu ne peux le connaître que grâce à une variable globale au thread et ces fonctions ne sont pas async sygnal safe.
Ou je n'ai pas compris...
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
Bruno Ducrot
On 12-10-2012, JKB wrote:
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller dans un gestionnaire de signal...
Certes, mais c'est aussi pourquoi j'ai écrit que c'était un truc bien crade (et donc à ne réserver qu'en cas d'urgence, avec les #define en fonction de l'OS qui vont bien).
-- Bruno Ducrot
A quoi ca sert que Ducrot hisse des carcasses ?
On 12-10-2012, JKB wrote:
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal
safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller
dans un gestionnaire de signal...
Certes, mais c'est aussi pourquoi j'ai écrit que c'était un truc bien crade
(et donc à ne réserver qu'en cas d'urgence, avec les #define en fonction
de l'OS qui vont bien).
Mouais, je me méfie. Lorsqu'une fonction n'est pas async signal safe, je ne sais pas pourquoi, mais je n'aime pas trop la coller dans un gestionnaire de signal...
Certes, mais c'est aussi pourquoi j'ai écrit que c'était un truc bien crade (et donc à ne réserver qu'en cas d'urgence, avec les #define en fonction de l'OS qui vont bien).