Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are system calls interrupted by signal?

My understanding is as following :

the blocking syscall would normally place the process in the 'TASK_INTERRUPTIBLE' state so that when a signal is delivered, the kernel places the process into 'TASK_RUNNING' state. And the process will be scheduled to run when the next timer tick happens , so that the syscall is interrupted .

But I did a small test , it failed . I worte a usermode process , which called sleep(). And I changed the process's state into TASK_RUNNING in kernel , but sleep() did not be interrupted at all and the process was still sleeping.

Then I tryed wake_up_process(process) , it failed.

Then I tryed set_tsk_thread_flag(process,TIF_SIGPENDING), it failed.

Then I tryed set_tsk_thread_flag(process,TIF_SIGPENDING) and wake_up_process(process), succeeded !! sleep() was interrupted and the process started to run .

So it's not that simple. Does anyone know how exactly are system calls interrupted by signal ?

like image 239
goodjesse Avatar asked Nov 02 '22 17:11

goodjesse


1 Answers

Check out __send_signal from signal.c. It calls complete_signal near the end, which eventually calls this little function:

void signal_wake_up_state(struct task_struct *t, unsigned int state)
{
        set_tsk_thread_flag(t, TIF_SIGPENDING);
        /*
         * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
         * case. We don't check t->state here because there is a race with it
         * executing another processor and just now entering stopped state.
         * By using wake_up_state, we ensure the process will wake up and
         * handle its death signal.
         */
        if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
                kick_process(t);
}

And that's how you do it. Note that it is not enough to set the thread flag: you have to use a wakeup function to ensure the process is scheduled.

like image 69
nneonneo Avatar answered Nov 09 '22 10:11

nneonneo