Pouvons-nous réinitialiser sigsetjmp pour qu’il renvoie «0» à nouveau (réinitialiser sigsetjmp)?

J’ai écrit un gestionnaire de fautes de segmentation, en utilisant sigsetjmp et siglongjmp. Une fois qu’il a été envoyé au gestionnaire de signal, j’appelle siglongjmp pour que l’instruction erronée soit ignorée.

Le problème est que je veux encore une fois causer SIGSEGV et utiliser le même gestionnaire, mais sigsetjmp renverra 1.

Comment réinitialiser sigsetjmp?

Voici mon code:

#include  #include  #include  #include  #include  #include  #include  #include  #include  sigjmp_buf env, env1; void SIGSEGV_handler(int signal) { printf("Segmentation fault caught\n"); siglongjmp(env, 1); } int main() { void * allocation; size_t size; static int devZerofd = -1; struct sigaction sa, sa1; sa.sa_handler=(void*)SIGSEGV_handler; sigaction(SIGSEGV, &sa, NULL); if ( devZerofd == -1 ) { devZerofd = open("/dev/zero", O_RDWR); if ( devZerofd < 0 ) perror("open() on /dev/zero failed"); } allocation = (caddr_t) mmap(0, 5000, PROT_READ|PROT_NONE, MAP_PRIVATE, devZerofd, 0); if ( allocation == (caddr_t)-1 ) fprintf(stderr, "mmap() failed "); if ( mprotect((caddr_t)allocation, 5000, PROT_NONE) < 0 ) fprintf(stderr, "mprotect failed"); else printf("mprotect done: memory allocated at address %u\n",allocation); if(sigsetjmp(env, 1)==0) { printf("Causing SIGSEGV: 1\n"); strcpy(allocation,"Hello, how are you"); } /****** This can't be done again as sigsetjmp won't return 0*****/ /* if(sigsetjmp(env, 1)==0) { printf("Causing SIGSEGV: 1\n"); strcpy(allocation,"Hello, how are you"); } */ } 

Vous avez mal compris le fonctionnement de [sig]setjmp . Si vous supprimez la mise en commentaire du code que vous pensez ne pas fonctionner, le comstackz et l’exécutez, vous verrez qu’il fonctionne réellement.

setjmp ne peut pas renvoyer zéro en appelant longjmp . Si vous appelez setjmp lui-même une seconde fois, même avec le même jmp_buf (comme vous le faites ici), il retournera zéro une seconde fois.

Au fait, vous avez un bug: vous n’avez pas configuré correctement la structure de vos parameters sigaction . Vous auriez dû faire ceci:

 struct sigaction sa; sa.sa_handler = SIGSEGV_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGSEGV, &sa, 0); 

L’utilisation de mmap est un peu délicate, mais pas vraiment buggée . Vous n’avez pas besoin de /dev/zero sur la plupart des plateformes actuelles, vous pouvez simplement utiliser MAP_ANON (certaines plateformes l’orthographient MAP_ANONYMOUS ) et un argument -1 fd. Et vous devriez utiliser getpagesize puis demander un nombre entier de pages.