Изучение альтернативного стека сигналов (различные способы его размещения)

Я экспериментирую с альтернативным стеком сигналов (man sigaltstack).

Два фрагмента кода, распределяющие стек по-разному:

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;
}

Я просто использовал SA_ONSTACK при регистрации сигнала. Во время планирования потока сигналов в pthread_create, если этот флаг установлен, 8 КБ стека выделяются следующим образом (SIGSTKSZ = 0x2000(8 КБ)):

  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;
  }

Другой способ сделать то же самое, все время регистрируя обработчик сигнала.

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;
}

В этом случае я не полагаюсь на то, что bionic выделит мне стек по умолчанию. Я выделяю свой собственный стек и использую его.

Итак, в обоих этих случаях я выделяю стеки сигналов по 8 КБ.

Я поставил внутренний обработчик сигнала while(1) и проверил proc/pid/maps после отправки сигнала процессу.

Вот результаты:

Метод 1 (стек, выделенный бионикой в ​​pthread_create):

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

Способ 2 (стек, выделенный приложением с помощью malloc):

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

Странно то, что, хотя я выделил только 8 КБ стека с помощью malloc() в методе 2, стек, похоже, выделил около 2 МБ (0x200000).

Пожалуйста, сообщите мне, что пошло не так, или это ожидаемое поведение.


person mk..    schedule 21.04.2015    source источник


Ответы (1)


Я видел случаи, когда информация в procfs о стеке неверна. Попробуйте напечатать адрес локальной переменной в обработчике сигнала. Держу пари, что вы обнаружите, что стек, который вы видите, является основным стеком.

Я не знаю, почему это происходит, но похоже, что это дело ядра. Я видел это и в Linux.

person nitzanms    schedule 05.08.2015