Почему я не могу остановить эту тему в ядре Linux? - PullRequest
1 голос
/ 14 февраля 2020

Edit: Clarification - это Linux код ядра.

Я отправляю SIGSTOP в поток, а затем вызываю wait_task_inactive, чтобы убедиться, что он остановился. А вот процессор RCU-зависает судя по логу ядра. У меня нет полученной спин-блокировки, и у меня должны быть права root. Следует также отметить, что поток, который я пытаюсь остановить, ни в коем случае не является особенным, это всего лишь однопоточный пользовательский скрипт. Кроме того, если у кого-то есть лучшее предложение о том, как убедиться, что поток проснулся, у меня все уши.

Имея в виду комментарий дерева Линуса в wait_task_inactive (), я могу думать только о двух возможностях :

  • Получен какой-то спинлок, о котором я не знаю. Я не думаю, что это.

  • Сигнал никогда не принимается и не обрабатывается потоком. Я не знаю, почему это могло произойти, кроме привилегий (то есть у меня недостаточно для отправки этого сигнала, в чем я сомневаюсь) или что wait_task_inactive имеет более высокий приоритет, и поток перестает ждать. Но процессоров много, а нить запущена мной, так что ...

В заключение я тоже застопорился!

Код:

void __send_signal(int sig_num, struct task_struct* p){
       struct siginfo info;
       unsigned long previous_state = p->state;
       int ret = 0;
       memset(&info, 0, sizeof(struct siginfo));
       info.si_signo = sig_num;
       info.si_code = 0;
       info.si_int = 1234;
       ret = send_sig_info(sig_num, &info,  p);
       /* Make sure the signal has been captured */
       switch(sig_num){
        case SIGSTOP:
            wait_task_inactive(p, p->state); /* It believe it stalls here */
            break;
        case SIGCONT:
            /* You definitely don't want to send a SIGCONT to a non-runnable thread. */
            while (previous_state != TASK_RUNNING && previous_state != TASK_WAKING &&
                     p->state == previous_state){
                cpu_relax();
            }
            break;
        default:
            printk(KERN_INFO "Signal %d was only sent...\n",sig_num);
       }
        if (ret < 0) {
               printk(KERN_ALERT "Error sending signal to PID %d\n",p->pid);
       }
}

Буфер ядра:

INFO: rcu_preempt detected stalls on CPUs/tasks:
[  184.838479]  6-...: (1 GPs behind) idle=315/140000000000000/0 softirq=40955/40956 fqs=2625 
[  184.846927]  (detected by 0, t=5252 jiffies, g=16297, c=16296, q=5592)
[  184.853610] Task dump for CPU 6:
[  184.856919] executable    R  running task    14288  5286   5172 0x0000000c
[  184.864198]  0000000000000086 ffffffff8a047a20 ffffb69449493b00 ffffffff89a6aab2
[  184.871992]  00000000ffffffff ffffb69449493b20 ffffffff894c004e 0000000000000006
[  184.879783]  000000000000002c ffffb69449493b38 ffffffff894c4fc9 ffffffff89a6a89a
[  184.887576] Call Trace:
[  184.890111]  [<ffffffff89a6aab2>] ? _raw_spin_unlock_irqrestore+0x32/0x60
[  184.896979]  [<ffffffff894c004e>] ? down_trylock+0x2e/0x40
[  184.902550]  [<ffffffff894c4fc9>] console_trylock+0x19/0x70
[  184.908202]  [<ffffffff89a6a89a>] ? _raw_spin_unlock+0x1a/0x30
[  184.914113]  [<ffffffff894c6eb5>] vprintk_emit+0x2f5/0x520
[  184.919679]  [<ffffffff894c724f>] vprintk_default+0x1f/0x30
[  184.925338]  [<ffffffff89577eb1>] printk+0x48/0x50
[  184.930222]  [<ffffffffc1a2c0db>] send_signal+0x70/0xe2 [module]
...