Re: killing a kernel thread with SIGKILL

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



http://www.scs.ch/~frey/linux/kernelthreads.html

/* We need to do a memory barrier here to be sure that
           the flags are visible on all CPUs.
        */
        mb();
        kill_proc(kthread->thread->pid, SIGKILL, 1);

        /* block till thread terminated */
        down(&kthread->startstop_sem);



Looking at kernel/sched.c:


3333
3334 int fastcall __sched wait_for_completion_interruptible(struct
completion *x)
3335 {
3336         int ret = 0;
3337
3338         might_sleep();
3339
3340         spin_lock_irq(&x->wait.lock);
3341         if (!x->done) {
3342                 DECLARE_WAITQUEUE(wait, current);
3343
3344                 wait.flags |= WQ_FLAG_EXCLUSIVE;
3345                 __add_wait_queue_tail(&x->wait, &wait);
3346                 do {
3347                         if (signal_pending(current)) {
3348                                 ret = -ERESTARTSYS;
3349                                 __remove_wait_queue(&x->wait, &wait);
3350                                 goto out;
3351                         }
3352                         __set_current_state(TASK_INTERRUPTIBLE);
3353                         spin_unlock_irq(&x->wait.lock);
3354                         schedule();
3355                         spin_lock_irq(&x->wait.lock);
3356                 } while (!x->done);
3357                 __remove_wait_queue(&x->wait, &wait);
3358         }
3359         x->done--;
3360 out:
3361         spin_unlock_irq(&x->wait.lock);
3362
3363         return ret;
3364 }

Your construction is very similar to sched.c.

add_wait_queue() will not block, or "wait".   The reason is because it
is just a simple list_add() call.   Notice also that the above
schedule() is after the signal_pending() processing, whereas yours is
the opposite.   Another big difference is that the above
implementation uses spin lock IRQ, and therefore signal can only come
into the small windows just before schedule(), after that it is
disabled immediately again.   Correct?

Neither can I explain your program's behavior either, as it does not
have any spin locks, and so signal can come in anytime?

>     /* the thread will sleep on this wait queue until it gets woken up */
>     add_wait_queue(&mkthread_waitqueue, &wait);
>
>     for (;;) {
>
>         /* guard against spurious wake up */
>         while (!condition) {
>         /* must be set before calling schedule() to
>          * avoid race condition */
>             set_current_state(TASK_INTERRUPTIBLE);
>
>         /* remove current from run queue and schedule a new process */
>             schedule();
>         }
>
>         /* we wake up here */
>         /* check for pending SIGKILL signal, die if there is any */
>         if (signal_pending(current)) {
>             kthread_debug("SIGKILL pending\n");
>             break;
>         }
>
>         /* is there a race condition ? */
>         condition = 0;
>         kthread_debug("mkthread woke up!\n");
>     }
>
>     /* change task stae to TASK_RUNNING before removing from wait queue */
>

Is the following really necessary?  I saw the code calling
remove_wait_queue() anytime.

>     set_current_state(TASK_RUNNING);
>     remove_wait_queue(&mkthread_waitqueue, &wait);
>
>

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux