-
The Pthread Hell
Hi!
If have this code:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
//#include <
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include "share/server.h"
#include "share/string.h"
int main (void)
{
/*if (fork () != -1)
{*/
int server;
int client;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
pthread_t *pthread;
unsigned short int pthreadc;
socklen_t size;
server = socket (PF_INET, SOCK_STREAM, 0);
printf ("socket %d:%d\n", server, errno);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons (15000);
printf ("Bind %d:%d\n",bind (server, (struct sockaddr *) &server_address, sizeof (server_address)), errno);
printf ("Listen %d:%d\n", listen (server, 5), errno);
while (1)
{
size = sizeof (client_address);
client = accept (server, (struct sockaddr *) &client_address, &size);
if (client > 0)
{
printf ("Client %d\n", client);
if (pthread == NULL)
{
pthread = malloc (sizeof (pthread_t));
}
else
{
pthreadc++;
pthread = realloc (pthread, sizeof (pthread_t) * (pthreadc + 1));
}
pthread_create ((pthread_t *) pthread [pthreadc], NULL, (void *) server_thread_go, &client);
}
else
{
printf ("Client2 %d: %d\n", client, errno);
//close (server);
}
}
pthread_exit (NULL);
close (server);
}
//}
int server_thread_go (void *client)
{
char depot [64];
char *data;
int value;
printf ("THREAD\n");
do
{
value = read ((int) client, &depot, 64);
if (value > 0)
{
if (data == NULL)
{
data = malloc (sizeof (char) * (strlen (depot) + 1));
}
else
{
data = realloc (data, sizeof (char) * (strlen (data) + 1 + strlen (depot) + 1));
}
data = strcat (data, depot);
}
}
while (value > 0);
if (!strncmp ("help", strtolower (data), strlen ("help")))
{
}
else if (!strncmp ("activate", strtolower (data), strlen ("activate")))
{
}
else if (!strncmp ("deactivate", strtolower (data), strlen ("deactivate")))
{
}
else if (!strncmp ("authenticate", strtolower (data), strlen ("authenticate")))
{
}
else if (!strncmp ("replicate", strtolower (data), strlen ("replacte")))
{
}
else if (!strncmp ("modify", strtolower (data), strlen ("modify")))
{
}
else if (!strncmp ("move", strtolower (data), strlen ("move")))
{
}
return 0;
}
But if I run it I get segementation fault caused by pthread_create. Why?
thanks
-
Probably because your indiscriminate casting has crippled the compiler from telling you where you screwed up.
> pthread_create ((pthread_t *) pthread [pthreadc], NULL, (void *) server_thread_go, &client);
Try for example
pthread_create ( &pthread [pthreadc], NULL, (void *) server_thread_go, &client);
Next step, prototype your thread function correctly. It is passed void*, and returns void*
It does NOT return an int as in your code.
void server_thread_go (void *client);
Then you can refine to
pthread_create ( &pthread [pthreadc], NULL, server_thread_go, &client);
Finally, you're passing a pointer to a local variable (&client). What value to do expect several threads to read out of that memory location when they're all competing for CPU time? It's not going to be what you set up that's for sure.
Since I guess you want to pass on the value stored in client at the moment you create the thread, then perhaps something like this.
Code:
int *temp = malloc( sizeof *temp );
*temp = client;
pthread_create ( &pthread [pthreadc], NULL, server_thread_go, temp); // thread free's memory
> pthread = realloc (pthread, sizeof (pthread_t) * (pthreadc + 1));
Search my previous posts on how to call realloc properly.
You need to assign to a temporary variable to make sure the realloc worked before trashing your only pointer to the memory.
And now your thread function
> int server_thread_go (void *client)
Change this to
void *server_thread_go (void *p)
> value = read ((int) client, &depot, 64);
To recover the client, do this
Code:
int client = *(int*)p;
free( p ); // got all the parameters, now free it (see main for allocation)
Then you can write
value = read ( client, depot, sizeof depot );
> data = strcat (data, depot);
There is no guarantee that the memory you get first time around with malloc has a \0 stored in the first location. So your strcat just appends to anywhere.
Also, see previous warnings about calling realloc.