Examining alternate signal stack (Different ways t

2020-05-06 08:16发布

问题:

I am experimenting on alternate signal stack(man sigaltstack).

Two pieces of code allocating stack differently:

int method1(void)
{
    struct sigaction act, oldact;

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = SignalHandler;
    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
        ALOGW("sigaction failed %s\n", strerror(errno));
        return -errno;
    }

    return 0;
}

I have simply used SA_ONSTACK while registering the signal. While the signal thread is being scheduled, in pthread_create, if this flag is set, a 8kb of stack is allocated as follows (SIGSTKSZ = 0x2000(8kb)):

  ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if (ss.ss_sp != MAP_FAILED) {
    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    sigaltstack(&ss, NULL);
    thread->alternate_signal_stack = ss.ss_sp;
  }

Another way of doing the same thing, all while registering the signal handler.

int method2(void)
{
    struct sigaction act, oldact;
    stack_t ss;

    ss.ss_sp = malloc(SIGSTKSZ);
    if (ss.ss_sp == NULL)
        return -ENOMEM;

    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    sigaltstack(&ss, NULL);

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = SignalHandler;
    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
        ALOGW("sigaction failed %s\n", strerror(errno));
        return -errno;
    }

    return 0;
}

In this case, I am not relying on bionic to allocate me the default stack. I am allocating my own stack and using it.

So, in both these cases I am allocating signal stacks of 8kb.

I have put a while(1) inside signal handler and checked proc/pid/maps after sending a signal to the process.

Here are the results :

Method 1 (stack allocated by bionic in pthread_create):

7faa8d1000-7faa8d3000 rw-p 00000000 00:00 0        [stack:6633]

Method 2 (stack allocated using malloc by the application):

7fb7300000-7fb7500000 rw-p 00000000 00:00 0        [stack:6567]

The strange thing is that while I allocated only 8kb of stack using malloc() in method2, the stack seems to have allocated around 2MB(0x200000).

Kindly advice me on what went wrong or is it expected behaviour.

回答1:

I've seen times where the information in procfs regarding the stack is incorrect. Try printing the address of a local variable in the signal handler. My bet is that you will find the stack you're seeing is the main stack.

I don't know why this happens but it looks like it's a kernel thing. I've seen it on Linux too.