I have problems with my code.
I have this client with posix queue. Is a posix queue comunication with a conc server.
The question is down.
mqd_t server;
mqd_t client;
struct request req; //char *name, int pos, int op...
struct reply rep; //int num, int ret...
struct mq_attr attr;
attr.mq_maxmsg = 1;
attr.mq_msgsize = sizeof(struct reply);
client = mq_open("/CLIENT", O_CREAT|O_RDONLY, 0700, &attr);
server = mq_open("/SERVER", O_WRONLY);
req.name = name;
req.op = 3;
mq_send (server, (const char *) &req, sizeof(struct req),0);
mq_receive(client, (char*)&rep, sizeof(struct reply), 0);
mq_close(server);
mq_close(client);
mq_unlink("/CLIENT");
And this server
struct db mydb[100]; //Struct with char*name....
for (int i = 0; i<100;i++){
strcpy(mydb[i].name,"");
mydb[i].vec =NULL;
mydb[i].size =0;
}
mqd_t server;
struct request mess;
struct mq_attr q_attr;
pthread_attr_t t_attr;
q_attr.mq_maxmsg = 10;
q_attr.mq_msgsize=sizeof(struct request);
server = mq_open ("/SERVER", O_CREAT|O_RDONLY, 0700, &q_attr);
if (server == -1){
perror("Er");
}
pthread_mutex_init (&mutex_msj, NULL);
pthread_cond_init (&cond_msj, NULL);
pthread_attr_init(&t_attr);
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
while(1){
pthread_t thid;
mq_receive(server, (char*) &mess, sizeof(struct request), 0);
AND HERE IS THE PROBLEM. WHEN I PRINF MESS.OP I WOULD RECIVE "3". The number that I asigned the client. And when I do this, mess.op have 0, not 3.
pthread_create(&thid, &t_attr, (void*)func, &mess);
...
...
...
...
}
Thanks.
It would appear that you are calling pthread_create() with a local (or automatic) variable mess which is sometimes deallocated before the thread is actually started. You need to allocate mess on the heap and be very careful to free it at the appropriate time.
Also (void *) func doesn't look right because,
The correct type is void *(*)(void *)
and it would appear as if you were ignoring compilation warnings, or forcing them to disappear by randomly casting a pointer to the type the compiler suggested.
Related
I writing a kernel module which accepts data(form of a structure) and passes back some data(same structure format) to the user-space. I can successfully receive the message from user but i get segmentation fault while i try tp dereference some of the members of the structure of the data received from kernel. I am using netlink socket API.
Sample code is as below:
user-space.c
#define NETLINK_USER 27
#define MAX_PAYLOAD 10000 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
Response *p;
Response *req;
test r1;
test r2;
int main()
{
char *data;
data = malloc(4096 * sizeof(char));;
data = "data from user";
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_LENGTH(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
p = malloc(2*sizeof(Response));
p[0].index = 1;
p[0].dataSize = 2;
p[0].data = data;
p[0].test2 = 3;
p[0].test3 = 4;
p[0].test4 = 5;
r1.t = 10;
r1.ip_addr = malloc(50*sizeof(char));
r1.ip_addr = "192.168.10.2";
p[0].test = &r1;
/* Extra for testing */
p[1].index = 2;
p[1].dataSize = 3;
//strcpy(p[1].data , "Data2 from User");
p[1].data = data;
p[1].test2 = 4;
p[1].test3 = 5;
p[1].test4 = 6;
r2.t = 20;
r2.ip_addr = malloc(50*sizeof(char));
r2.ip_addr = "192.168.20.2";
p[1].test = &r2;
memcpy(NLMSG_DATA(nlh), (void *)p, 2 * sizeof(*p));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
//recvmsg(sock_fd, &msg, 0);
req = (Response*)NLMSG_DATA(nlh);
printf("Recieved from Kernel:\n");
printf("index %d\n", req[0].index);
printf("dataSize %d\n", req[0].dataSize);
printf("data: %s\n", req[0].data); <---Segmentation fault from here
printf("test2 %d\n", req[0].test2);
printf("test3 %d\n", req[0].test3);
printf("test4 %d\n", req[0].test4);
printf("contents of test structure are %d,%s\n",req[0].test->t,req[0].test->ip_addr); <-----Segmentation fault
close(sock_fd);
Kernel_module.c
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#define NETLINK_USER 27
struct sock *nl_sk = NULL;
typedef struct _Response Response;
typedef struct _test test;
struct _test{
int t;
char *ip_addr;
};
struct _Response
{
int index;
int dataSize;
char *data;
int test2;
int test3;
int test4;
test *test;
};
static void hello_nl_recv_msg(struct sk_buff *skb) {
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
int res;
Response *req;
Response *req1;
test t;
t.t = 1;
t.ip_addr = kmalloc(50*sizeof(char), GFP_KERNEL);
t.ip_addr = "129.63.45.1";
req1 = (Response *)kmalloc_array(2, sizeof(Response), GFP_KERNEL);
char *data;
data = kmalloc(4096 * sizeof(char), GFP_KERNEL);
data = "data from kernel";
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size= 2 * sizeof(*req1);
req1[0].index = 100;
req1[0].dataSize = 100;
req1[0].data = data;
req1[0].test2 = 100;
req1[0].test3 = 100;
req1[0].test4 = 100;
req1[0].test = &t;
printk("Sending to Userspace:\n");
/*Second set of message*/
req1[1].index = 102;
req1[1].dataSize = 103;
//strcpy(req1[1].data , "Data from Kernel");
req1[1].data = data;
req1[1].test2 = 100;
req1[1].test3 = 100;
req1[1].test4 = 100;
req1[1].test = &t;
nlh=(struct nlmsghdr*)skb->data;
req = (Response *)NLMSG_DATA(nlh); <--message received from user-space
printk("Recieved from Userspace:\n");
printk("index %d\n", req[0].index);
printk("dataSize %d\n", req[0].dataSize);
printk("data: %s\n", req[0].data);
printk("test2 %d\n", req[0].test2);
printk("test3 %d\n", req[0].test3);
printk("test4 %d\n", req[0].test4);
printk("contents of test are %d, %s\n",req[0].test->t,req[0].test->ip_addr);
printk("Next set of data\n");
printk("Recieved from Userspace:\n");
printk("index %d\n", req[1].index);
printk("dataSize %d\n", req[1].dataSize);
printk("data: %s\n", req[1].data);
printk("test2 %d\n", req[1].test2);
printk("test3 %d\n", req[1].test3);
printk("test4 %d\n", req[1].test4);
printk("contents of test are %d, %s\n",req[1].test->t,req[1].test->ip_addr);
pid = nlh->nlmsg_pid; /*pid of sending process */
skb_out = nlmsg_new(10000,0);
if(!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,10000,0);
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
/*End of second set*/
memcpy(NLMSG_DATA(nlh), req1, 2 * sizeof(*req1));
res=nlmsg_unicast(nl_sk,skb_out,pid);
if(res<0)
printk(KERN_INFO "Error while sending bak to user\n");
}
static int __init hello_init(void) {
printk("Entering: %s\n",__FUNCTION__);
struct netlink_kernel_cfg cfg = {
.input = hello_nl_recv_msg,
};
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
if(!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(hello_init); module_exit(hello_exit);
MODULE_LICENSE("GPL");
}
global.h
#ifndef __GLOBAL_H
#define __GLOBAL_H
typedef struct _Response Response;
typedef struct _test test;
struct _test{
int t;
char *ip_addr;
};
struct _Response
{
int index;
int dataSize;
char *data;
int test2;
int test3;
int test4;
test *test;
};
#endif
Basically the problem is with the pointers. If i use char data[4096] instead of character pointer, i receive the message. But i get segmentation fault while dereferencing the test structure. How to resolve this issue?
Thanks
This code is very wrong and full critique is likely unnecessary, so I'll just point out 2 most obvious types of violations.
char *data;
data = kmalloc(4096 * sizeof(char), GFP_KERNEL);
data = "data from kernel";
First a nit: sizeof(char) is guaranteed to be 1. The real problem though is that this instantly overwrites the value of data, losing the pointer returned by malloc. This is present in multiple places in the code.
req = (Response *)NLMSG_DATA(nlh); <--message received from user-space
printk("Recieved from Userspace:\n");
printk("index %d\n", req[0].index);
printk("dataSize %d\n", req[0].dataSize);
printk("data: %s\n", req[0].data);
This code, while likely "works", is completely wrong. The userspace buffer (.data) cannot be safely accessed in this manner and on some architectures it cannot be accessed at all. It may "work" because the complete address space is divided into both the kernel and userspace and the kernel in principle has access there. Problems arise if the pointer is to something totally bogus or within the kernel, or maybe to something unmapped.
The userspace portion of the code tries to do a reverse trick and unsurprisingly that fails -- you can't access kernel memory or there would be no security whatsoever.
The problem only arises because the protocol is wrong. You should have a buffer allocated in userspace and a variable holding its size. Then you can tell the kernel where to put data (and how much tops).
Either way, I think you are not ready for kernel work at this point and as such strongly suggest sticking to userspace for the time being.
I have the following code serving as main loop for a server that accepts incoming socket connections.
At the moment the macro OperationMode is defined as 1 so it will execute the pthread logic.
for (hit = 1 ;; hit++) {
printf("Got here\n\n");
length = sizeof(cli_addr);
/* block waiting for clients */
socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);
if (socketfd < 0)
printf("ERROR system call - accept error\n");
else
{
printf("Testing\n\n\n");
#ifdef OperationMode
pthread_t thread_id;
if(pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL))
{
perror("could not create thread");
return 1;
}
#else
pid = fork();
if(pid==0)
{
ftp(socketfd, hit);
}
else
{
close(socketfd);
kill(pid, SIGCHLD);
}
#endif
}
}
I'm able to create a thread for the first incoming socket connection but once I iterate over the loop I get segmentation fault error in the line
socketfd = accept(listened, (struct sockaddr *) &cli_addr, &length);
My attendFTP function has the following code
void *attendFTP(int fd, int hit)
{
ftp(fd, hit);
return NULL;
}
This works perfect for the fork implementation. How can I fix the segmentation fault error?
pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL);
This code passess result of a call to attendFTP() with given paramters - and this result is always NULL.
So pthread_create is trying to launch a function at NULL address and, correspondingly, fails.
If you run your compiler with -pedantic argument, compiler will tell you that what you are doing is wrong. Without -pedantic, gcc allows for some 'extensions', which might hide errors. Btw, this is why -pedantic is, in my view, a must.
What you actually want is to pass some arguments to your threading function. Unfortunately, it is really convoluted in C pthreads, and requires you to allocate and deallocate the said struct. Something like this:
struct args {
int fd;
int hit;
};
...
pthread_t thread_id;
struct args* args = malloc(sizeof(struct args));
args->fd = socketfd;
args->hit = hit;
if(pthread_create(&thread_id, NULL, attendFTP, args))
....
void* attendFTP(void* vargs)
{
struct args* args = vargs;
ftp(args->fd, args->hit);
free(args);
return NULL;
}
I am working on a multi-threaded server application.The server accepts connections from multiple devices and assign each connection a thread.The thread is a looping thread i.e it uses a while loop which iterates until the client closes the connection.
Currently when multiple clients got connected to the server only single client is able to communicate i.e the data sent by a single device is received at the server side and updated in database the other devices remain connected to server but no data is received from them. what seems the reason to me (not sure only assuming) is that only a single thread remains executing and other threads don't get the turn to execute.
so I want to schedule threads in round robin so that each thread executes.How can I schedule threads in round robin
I got the following code on-line but it was not able to schedule the threads in round robin.
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
Here is my code which creates threads:
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,(socklen_t*)&clntSock);
if(connfd > 0){
conn_desc = connfd;
puts("Connection accepted");
if(pthread_create( &thr, &attr , connection_handler , (void*)&conn_desc) < 0){
perror("could not create thread");
}
Your problem is not related to the scheduler policy. You have a potential race condition in your code.
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
conn_desc = connfd;
pthread_create(&thr,&attr,connection_handler,(void*) &conn_desc);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = *(int *) ptr;
...
return (void *) 0;
}
The race is that the parent can fire a second thread before the first thread has been able to dereference ptr. Thus, two threads will use the same value for connfd.
To correct this, we need to slightly modify the calling sequence to a pass-by-value:
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
pthread_create(&thr,&attr,connection_handler,(void*) connfd);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = (int) ptr;
...
return (void *) 0;
}
Side note: It is guaranteed that an int can be passed inside a pointer in this manner, but for sticklers, see below.
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
ptr = malloc(sizeof(int));
*ptr = connfd;
pthread_create(&thr,&attr,connection_handler,(void*) ptr);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = *(int *) ptr;
free(ptr);
...
return (void *) 0;
}
I have created an app in which I want a thread to handle listen-UDP separately and make me a buffer, but when I try to pass it to thread it says there are compatibility issues
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
start, // thread function name
&buffer, // argument to thread function
0, // use default creation flags
&dwThreadId);
my start function is
void start(buffer_t *buffer)
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
}
and the error is
1 IntelliSense: argument of type "void (*)(buffer_t *buffer)" is incompatible with parameter of type "LPTHREAD_START_ROUTINE" c:\users\madihamalik\documents\visual studio 2010\projects\udp listener\udp listener\listerner.c 189 12 UDP listener
Try below code that might help you..
DWORD start(LPVOID lpdwThreadParam)
{
buffer_t *buffer = (buffer_t *)lpdwThreadParam; //Type cast your argument here
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[BUFLEN];
WSADATA wsa;
...
}
I am trying to pass a structure when creating a thread but does not seem to work correctly!
Here is the structure:
struct analyse_data {
int verbose; //should be 1 or 0
};
Note that verbose can only be 1 or 0 and nothing else.
Here is the method being called (note it can be called multiple times by another method):
void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
int verbose) {
static bool thread_settings_initialised = false;
printf("Verbose: %d\n", verbose); //Prints 1 or 0
//Only run the first time dispatch method runs
if (thread_settings_initialised == false){
thread_settings_initialised = true;
//...
//Set mutex for the appropriate variables to remain thread safe
//...
//Set attr so threads are "Detached"
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//Set pthread_cond_init
//...
}
//Put parameters into a struct so can be sent in a thread
struct analyse_data data;
data.verbose = verbose;
//...
pthread_t tid;
printf("data.verbose: %d\n", data.verbose); //This prints 1 or 0
int rc = pthread_create( &tid, &attr, bar, (void *) &data);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
and this is the method thats being called by the thread:
void analyse(void *thread_data) {
struct analyse_data *data;
data = (struct analyse_data *) thread_data;
int verbose = data->verbose;
printf("Verbose = %d\n", verbose ); //Prints weird numbers like -547845...
}
As you can see from my comments, the value of verbose changes when being used inside the method. Why? What am I doing Wrong?
Many Thanks!
Update (thanks to JS1)
I updated my code to use a pointer:
void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
int verbose) {
static bool thread_settings_initialised = false;
printf("Verbose: %d\n", verbose); //Prints 1 or 0
//...
//Put parameters into a struct so can be sent in a thread
struct analyse_data *data = malloc(sizeof(struct analyse_data)); //NEW
data->verbose = verbose;
//...
pthread_t tid;
printf("data.verbose: %d\n", data.verbose); //This prints 1 or 0
int rc = pthread_create( &tid, &attr, bar, (void *) data);
//...
}
But now the analyse() method always outputs 0, even when verbose is 1!
You should not pass a stack variable to pthread_create. Notice that data is local to the function dispatch and will be out of scope when dispatch returns. You should instead either use malloc to allocate data, or use a static or global variable.
If you use the malloc method, it will look like this:
struct analyse_data *data = malloc(sizeof(struct analyse_data));
data->verbose = verbose;
int rc = pthread_create( &tid, &attr, bar, data);
You must remember to not call free on data from dispatch. The memory should "belong" to the thread, so you should eventually call free on data from the thread when you are done using the contents of data.