I'm trying to use the third argument of a SA_SIGINFO sigaction to jump to the interrupted context directly.
Thought this:
void action(int Sig, siginfo_t *Info, void *Uctx) {
ucontext_t *uc = Uctx; setcontext(uc);
}
would have the same effect as just:
void action(int Sig, siginfo_t *Info, void *Uctx) {
return;
}
but curiously it accepts three signals (that invoke the setcontext-calling handler), and then it segfaults
in setcontext:
Dump of assembler code for function setcontext:
0x00007ffff7a34180 <+0>: push %rdi
0x00007ffff7a34181 <+1>: lea 0x128(%rdi),%rsi
0x00007ffff7a34188 <+8>: xor %edx,%edx
0x00007ffff7a3418a <+10>: mov $0x2,%edi
0x00007ffff7a3418f <+15>: mov $0x8,%r10d
0x00007ffff7a34195 <+21>: mov $0xe,%eax
0x00007ffff7a3419a <+26>: syscall
0x00007ffff7a3419c <+28>: pop %rdi
0x00007ffff7a3419d <+29>: cmp $0xfffffffffffff001,%rax
0x00007ffff7a341a3 <+35>: jae 0x7ffff7a34200 <setcontext+128>
0x00007ffff7a341a5 <+37>: mov 0xe0(%rdi),%rcx
--Type <RET> for more, q to quit, c to continue without paging--
0x00007ffff7a341ac <+44>: fldenv (%rcx)
=> 0x00007ffff7a341ae <+46>: ldmxcsr 0x1c0(%rdi)
0x00007ffff7a341b5 <+53>: mov 0xa0(%rdi),%rsp
0x00007ffff7a341bc <+60>: mov 0x80(%rdi),%rbx
and the fault address shown by strace is 0 (a catchable SIGSEGV).
Here's an example program that's using a timer to send the three signals:
#include <unistd.h>
#include <sys/time.h>
#include <ucontext.h>
#include <signal.h>
void action(int Sig, siginfo_t *Info, void *Uctx) {
ucontext_t *uc = Uctx; setcontext(uc);
}
int main(void) {
char ch[100];
sigaction(SIGALRM, &(struct sigaction){.sa_sigaction = action, .sa_flags = SA_SIGINFO}, 0);
setitimer(ITIMER_REAL, &(struct itimerval){.it_interval.tv_sec = 1,.it_value.tv_sec = 1}, 0);
write(1, "enter\n", 6);
for (;;) {
write(1, "{\n", 2);
read(0, &ch[0], sizeof(ch));
write(1, "}\n", 2);
}
}
What is going on in this situation?