----- Original Message -----
Sent: Tuesday, January 24, 2006 7:25
PM
Subject: Sock_recvmsg() blocks and is
not killable
Hi,
I had started a kernel thread which is supposed
to listen to a particular UDP port. Now when I try to kill the thread, the
thread keeps waiting on the recv call.
What is a clean way of killing the thread. I
cannot make the recv function unblocking as I have rather too few packets
coming on the port and the processing is done on an embedded platform. Non
blocking recv call would rather eat up power and increase the CPU
utilization.
/* Receive Call */
UWORD32 recv(struct socket * sockfd, UWORD8 * data, UWORD32
size,
UWORD32 flags)
{
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
struct sockaddr_in
sin;
UWORD32 len =
0;
msg.msg_name =
&sin;
msg.msg_namelen = sizeof(struct sockaddr_in);
iov.iov_base = data;
iov.iov_len = size;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen =
0;
msg.msg_flags =
flags;
oldfs = get_fs();
set_fs(KERNEL_DS);
len = sock_recvmsg(sockfd,
&msg, iov.iov_len, 0);
/* If the size is more than
zero, check for the source address */
/* It should be same as the server
address
*/
if(len >
0)
{
if(serveraddr.sin_addr.s_addr != sin.sin_addr.s_addr)
{
len = 0;
}
}
set_fs(oldfs);
return len;
}
WORD32 rthreadd(void * arg)
{
UWORD32 len = 0;
UWORD8 >
UWORD8 *data_buff = NULL;
UWORD16 rx_buff_size = 1500;
/* Deamonize and unmask the
signkill for this thread */
_daemonize("Threadd");
allow_signal(SIGKILL);
/* This buffer will be used to
recieve the incoming packets */
data_buff = kmalloc(rx_buff_size, 0);
if(data_buff == NULL)
{
>
}
/* Receive the packet on the
port
*/
/* If the packet is
received, process the packet in the FSM */
while(one)
{
len = 0;
/*
Waits for a packet, once a packet has been received, process it */
while(len <= 0)
{
len = recv(g_socket, data_buff, rx_buff_size, 0);
}
if(get_pending_signal(current))
{
break;
}
/* Process the
received packet */
process_host_rx(data_buff,
len);
}
/* Free the data buffer
*/
kfree(data_buff);
sock_release(g_socket);
return 0;
}
Init_thread()
{
g_pid = -1;
/* Create the socket for the
radius client */
error
= sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &g_socket);
if (error < 0)
{
return BFALSE;
}
g_socket->sk->sk_allocation =
GFP_ATOMIC;
error =
(*g_socket->ops->bind)(g_socket,
(struct sockaddr *)&clientaddr, sizeof(clientaddr));
if (error < 0)
{
return BFALSE;
}
/* Start the kernet thread
*/
g_pid =
kernel_thread(radiusd, 0, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
if (g_pid < 0)
{
return BFALSE;
}
return BTRUE;
}
void stop_client(void)
{
If(g_pid !=
-1)
{
Killproc(g_pid, SIGKILL, 1);
}
}
Regards,
Jitesh
Shah
T8056601107
Bangalore-560025