killing a kernel thread with SIGKILL

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

 



Hi

I have written a kernel module that creates a kernel thread in its init method. The kernel thread sleeps until someone calls the module's read method to wake it up and then prints some log messages. I have allowed SIGKILL signal to be deliverable to the thread. But I can't kill the thread with SIGKILL.

My questions are -

   1. Why is the thread not receiving SIGKILL even after allowing it? How can I kill the thread before unloading the module?

   2. Is there any race condition in the way I am testing the condition to check against spurious signals? Should I use lock before/after access to "condition" variable?

code goes below -

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <asm/signal.h>
#include <linux/wait.h>

#define kthread_debug(fmt, arg...) \
    printk(KERN_ALERT fmt, ##arg)

static int kthread_major = 0;
/* declare and initialize wait queue head used for sleeping */
static DECLARE_WAIT_QUEUE_HEAD(mkthread_waitqueue);
static int condition;
rwlock_t mevent_lock;

/* mkthread is the entry point for kernel thread, we don't use argument */
static int
mkthread(void *arg)
{
    kthread_debug("mkthread created\n");
    try_module_get(THIS_MODULE);
    
    /* declare wait queue entry */
    DECLARE_WAITQUEUE(wait, current);                

    /*  all the gunge required to become a kernel thread without
        attached user resources in one place where it belongs.  */
    daemonize("mkthread");
    
    /* since daemonize blocks all signal we enable only SIGKILL here */
    allow_signal(SIGKILL);        

    /* 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 */    
    set_current_state(TASK_RUNNING);
    remove_wait_queue(&mkthread_waitqueue, &wait);        

    module_put(THIS_MODULE);

    return 0;    
}

static ssize_t
kthread_read(struct file *filp, char *ubuf, size_t count, loff_t *f_pos)
{
    condition = 1;
    wake_up_interruptible(&mkthread_waitqueue);    
    
    return 0;
}

/* the open function is used to create kernel thread */
static int
kthread_open(struct inode* indode, struct file* filp)
{
    kthread_debug("kthread_open done\n");

        return 0;
}

struct file_operations kthread_ops = {
    .owner = THIS_MODULE,
    .open = kthread_open,
    .read = kthread_read
};

static void
__exit kthread_module_exit(void)
{
    kthread_debug("kthread_module_exit done\n");
}

static int
__init kthread_module_init(void)
{
    int ret = 0;

    ret = register_chrdev(kthread_major, "kthread", &kthread_ops);
    if (ret < 0) {
        printk(KERN_ERR "register_chrdev() error\n");        
    }
    kthread_major = ret;    
    kthread_debug("kthread module registered with major: %d\n", kthread_major);    

    kernel_thread(mkthread, 0, CLONE_KERNEL);
    
    kthread_debug("kthread_module_init done\n");
    
    return ret;
}

module_init(kthread_module_init);
module_exit(kthread_module_exit);


Be a better Heartthrob. Get better relationship answers from someone who knows.
Yahoo! Answers - Check it out.

[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