// Test source and desired /real output: #include <signal.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h>
void handler(int sig) { unsigned int a; // to prevent uninitialized stack, normally a = 0 if ( a>10 ) a = 0; a = a + 1; printf ("new value: %d\n" , a ); if (a > 7) _exit(a); return; } int main() { int ret; char * stackA = malloc(SIGSTKSZ); char * stackB = malloc(SIGSTKSZ); stack_t ssA = { .ss_size = SIGSTKSZ, .ss_sp = stackA, }; stack_t ssB = { .ss_size = SIGSTKSZ, .ss_sp = stackB, }; struct sigaction sa = { .sa_handler = handler, .sa_flags = SA_ONSTACK }; // no error checking, only debug output ret = sigfillset(&sa.sa_mask); printf ( "Sigfillset: %d\n" , ret ); ret = sigaction(SIGUSR1, &sa, 0); printf ( "Sigaction: %d\n" , ret ); while (1) { printf ("On stack A -- " ); ret = sigaltstack(&ssA, 0); printf ( "sigaltstack return: %d -- " , ret ); kill(0, SIGUSR1); sleep(1); printf (" -- " ); kill(0, SIGUSR1); sleep(1); printf ("On stack B -- " ); ret = sigaltstack(&ssB, 0); printf ( "sigaltstack return: %d -- " , ret ); kill(0, SIGUSR1); sleep(1); } } /* Desired output: Sigfillset: 0 Sigaction: 0 On stack A -- sigaltstack return: 0 -- new value: 1 -- new value: 2 On stack B -- sigaltstack return: 0 -- new value: 1 On stack A -- sigaltstack return: 0 -- new value: 3 -- new value: 4 On stack B -- sigaltstack return: 0 -- new value: 2 On stack A -- sigaltstack return: 0 -- new value: 5 -- new value: 6 On stack B -- sigaltstack return: 0 -- new value: 3 On stack A -- sigaltstack return: 0 -- new value: 7 -- new value: 8 Output for ppc without patch: Sigfillset: 0 Sigaction: 0 On stack A -- sigaltstack return: 0 -- new value: 1 -- new value: 2 On stack B -- sigaltstack return: 0 -- new value: 3 // WRONG!! On stack A -- sigaltstack return: 0 -- new value: 4 -- new value: 5 // WRONG AGAIN! ... */