kernel thread blocked in sock_recvmsg() not kill-able

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

 



hi,

i've written an example code (attached) of a module that starts a kernel
thread listening in a UDP socket. it receives correctly datagrams

but the kernel thread remains blocked in sock_recvmsg(), in the main
loop:

/* main loop */
for (;;)
{
	memset(&buf, 0, bufsize);
	iov.iov_base = buf;
	iov.iov_len = len;
	msg.msg_flags = 0;
	msg.msg_name = addr;
	msg.msg_namelen  = sizeof(struct sockaddr_in);
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;

	oldfs = get_fs();
	set_fs(KERNEL_DS);
	size = sock_recvmsg(kthread->sock,&msg,len,0);
	if (kthread->force_exit == 1)
		break;

	if (size < 0)
		printk(KERN_INFO MODULE_PREFIX"sock_recvmsg error = %d\n", size);
	else
		printk(KERN_INFO MODULE_PREFIX"received %d bytes\n", size);
}
	
when the module is unloaded, the module remains blocked until a datagram
is received and the 'main loop' ends

in the cleanup function i try to kill the kernel thread with no result:

/* ksocket_exit */
kthread->force_exit = 1;

if (kthread->thread!=NULL)
	task = find_task_by_pid(kthread->thread->pid);

if (task==NULL)
	printk(KERN_INFO MODULE_PREFIX"no kernel thread to kill\n");
else {
	/* wake up kernel thread with a SIGKILL signal */
	printk(KERN_INFO MODULE_PREFIX"attempting to terminate kernel thread
(pid %d)\n",kthread->thread->pid);
	lock_kernel();
	err = kill_proc(kthread->thread->pid, SIGKILL, 1);
	unlock_kernel();

	/* wait for kernel thread to die */
	if (err < 0)
		printk(KERN_INFO MODULE_PREFIX"unknown error %d while trying to
terminate kernel thread\n",-err);
	else {
		while (kthread->running == 1)
			msleep(10);
		printk(KERN_INFO MODULE_PREFIX"succesfully terminated kernel thread!
\n");
	}
}


what is the correct way to force the kernel thread to exit?

thanks,

toni


#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/string.h>

#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/syscalls.h>
#include <linux/delay.h>

#define DEFAULT_PORT 2323
#define MODULE_PREFIX "ksocket: "

struct kthread_t
{
	struct task_struct *thread;
	struct socket *sock;
	int fd;
	struct sockaddr_in addr;
	int running;
	int force_exit;
};

/* function prototypes */
int ksocket_receive(struct socket *sock, struct sockaddr_in *addr, unsigned char *buf, int len);

struct socket *sock;
struct kthread_t *kthread = NULL;

static void kvoipmonitor_start(void)
{
	int size, err;
	int bufsize = 1024;
	unsigned char buf[bufsize];

	/* kernel thread initialization */
	lock_kernel();
	kthread->running = 1;
	kthread->thread = current;
	current->flags |= PF_NOFREEZE;

	/* set signal mask to what we want to respond */
	siginitsetinv(&current->blocked, sigmask(SIGKILL));
	allow_signal(SIGKILL);

	/* daemonize and release the big kernel lock */
	daemonize("ksocket");
	unlock_kernel();

	/* create a socket */
	if ((err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &kthread->sock)) < 0) {
		printk(KERN_INFO MODULE_PREFIX"Could not create a datagram socket, error = %d\n", -ENXIO);
		goto out;
	}

	kthread->fd = sock_map_fd(kthread->sock);
	if (kthread->fd < 0)
		goto close_and_out;

	memset(&kthread->addr, 0, sizeof(struct sockaddr));
	kthread->addr.sin_family		= AF_INET;
	kthread->addr.sin_addr.s_addr	= htonl(INADDR_ANY);
	kthread->addr.sin_port		= htons(DEFAULT_PORT);

	if ((err = kthread->sock->ops->bind(kthread->sock, (struct sockaddr *)&kthread->addr, sizeof(struct sockaddr))) < 0) {
		printk(KERN_INFO MODULE_PREFIX"Could not bind to socket, error = %d\n", -err);
		goto close_and_out;
	}
	kthread->sock->sk->sk_family = AF_INET;

	printk(KERN_INFO MODULE_PREFIX"listening on port %d (server state %d)\n", DEFAULT_PORT, kthread->sock->sk->sk_state);

	/* main loop */
	for (;;)
	{
		memset(&buf, 0, bufsize);
		size = ksocket_receive(kthread->sock, &kthread->addr, buf, bufsize);

		if (kthread->force_exit == 1)
			goto close_and_out;

		if (size < 0)
			printk(KERN_INFO MODULE_PREFIX"error getting datagram, sock_recvmsg error = %d\n", size);
		else
			printk(KERN_INFO MODULE_PREFIX"received %d bytes\n", size);
	}

close_and_out:
	sock_release(kthread->sock);
	kthread->sock = NULL;

out:
	kthread->thread = NULL;
	kthread->running = 0;
}

int ksocket_receive(struct socket* sock, struct sockaddr_in* addr, unsigned char* buf, int len)
{
	struct msghdr msg;
	struct iovec iov;
	mm_segment_t oldfs;
	int size = 0;

	if (sock->sk==NULL) return 0;

	iov.iov_base = buf;
	iov.iov_len = len;

	msg.msg_flags = 0;
	msg.msg_name = addr;
	msg.msg_namelen  = sizeof(struct sockaddr_in);
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;

	oldfs = get_fs();
	set_fs(KERNEL_DS);
	size = sock_recvmsg(sock,&msg,len,0);
	set_fs(oldfs);

	return size;
}

int __init ksocket_init(void)
{
	int err;
	
	kthread = kmalloc(sizeof(struct kthread_t), GFP_KERNEL);
	memset(kthread, 0, sizeof(struct kthread_t));
	kthread->thread = NULL;
	kthread->force_exit = 0;
	
	/* start kernel thread */
	err = kernel_thread((void *)kvoipmonitor_start, NULL, CLONE_KERNEL | SIGCHLD | SIGKILL | SIGINT | SIGTERM);
	if (err < 0) {
		printk(KERN_INFO MODULE_PREFIX"unable to start kernel thread\n");
		kfree(kthread);
		kthread = NULL;
		return -ENOMEM;
	}

	return 0;
}

void __exit ksocket_exit(void)
{
	int err;
	struct task_struct *task=NULL;

	kthread->force_exit = 1;
	
	if (kthread->thread!=NULL)
		task = find_task_by_pid(kthread->thread->pid);

	if (task==NULL)
		printk(KERN_INFO MODULE_PREFIX"no kernel thread to kill\n");
	else {
		/* wake up kernel thread with a SIGKILL signal */
		printk(KERN_INFO MODULE_PREFIX"attempting to terminate kernel thread (pid %d)\n",kthread->thread->pid);
		lock_kernel();
		err = kill_proc(kthread->thread->pid, SIGKILL, 1);
		unlock_kernel();

		/* wait for kernel thread to die */
		if (err < 0)
			printk(KERN_INFO MODULE_PREFIX"unknown error %d while trying to terminate kernel thread\n",-err);
		else {
			while (kthread->running == 1)
				msleep(10);
			printk(KERN_INFO MODULE_PREFIX"succesfully terminated kernel thread!\n");
		}
	}
	kfree(kthread);
	kthread = NULL;

	printk(KERN_INFO MODULE_PREFIX"module unloaded\n");
}

/* init and cleanup functions */
module_init(ksocket_init);
module_exit(ksocket_exit);

/* module information */
MODULE_DESCRIPTION("kernel thread listening on a UDP socket (code example)");
MODULE_AUTHOR("toni <agar9938@xxxxxxxxxxxxxxxxxx>");
MODULE_LICENSE("GPL");

[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