Reputation: 467
this is a simple program I've been working on that listens to a socket, and starts a new thread to handle each connection to said socket.
In my while loop I get a Segmentation Fault, that has something to do with pthread_create
(if I comment that line out the program loops properly). My knowledge of pointers is mediocre at best, and debugging with gdb didn't yield anything of value. This is gdb's output:
#0 0x0000000000000000 in ?? ()
#1 0x000000080064f4f1 in pthread_getprio () from /lib/libthr.so.3
#2 0x0000000000000000 in ?? ()
Error accessing memory address 0x7fffffbff000: Bad address.
The program gets through the while loop once successfully, and properly receives and responds to a connection at the socket, but then before getting into the second while loop, the program fails on a Segmentation Fault error.
Here's a condensed version of my program:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <pthread.h>
#define UNIX_PATH_MAX 100
#define SOCK_PATH "/tmp/demo_socket"
/*===============> CONNECTION HANDLER FUNCTION <=================*/
void *connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
nbytes = read(connection_fd, buffer, 256);
buffer[nbytes] = 0;
printf("\tMESSAGE FROM CLIENT: %s\n", buffer);
nbytes = snprintf(buffer, 256, "Hello from the server!");
write(connection_fd, buffer, nbytes);
close(connection_fd);
return;
}
/*==========================> MAIN <=============================*/
int main(void)
{
struct sockaddr_un addr; //socket address information
int sock_fd, conn_fd; //socket file descriptors
socklen_t addr_len = sizeof(struct sockaddr_un); //size of sockaddr_un structure
pid_t child_pid; //pid holder
pthread_t thread; // thread identifier
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_fd < 0)
return 1;
unlink(SOCK_PATH);
memset(&addr, 0, addr_len);
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1); // Copies up to sizeof(addr.sun_path)-1 bytes from SOCK_PATH into addr.sun_path
printf("> Socket sun_family = %d (AF_UNIX), Socket sun_path = %s ...\n", addr.sun_family, addr.sun_path);
/*----------------------FAIL CHECKS-------------------------*/
if (bind(sock_fd, (struct sockaddr *) &addr, addr_len) != 0)
return 1;
if (listen(sock_fd, 5) != 0)
return 1;
printf("> Listening to socket bound at %s ...\n\n", SOCK_PATH);
/*--------------------WHILE LOOP----------------------------*/
while ( (conn_fd = accept(sock_fd, (struct sockaddr *) &addr, &addr_len)) > -1) {
pthread_create(&thread , NULL, connection_handler(conn_fd), NULL);
printf("> Closing connection at %d inside server process ...\n", conn_fd);
close(conn_fd);
printf("> Reached bottom of loop!\n");
}
/*---------------------------FIN------------------------------*/
close(sock_fd);
unlink(SOCK_PATH);
printf("> Socket closed and unlinked from path ... Done!\n ");
return 0;
}
Any help would be greatly appreciated!
Upvotes: 1
Views: 3267
Reputation: 500357
This is wrong:
pthread_create(&thread , NULL, connection_handler(conn_fd), NULL);
pthread_create
requires the address of the function to run in the new thread. What your code does is call connection_handler
in the main thread and then pass the result of connection_handler
to pthread_create as the function address.
What you need is the following:
pthread_create(&thread , NULL, connection_handler, (void*)conn_fd);
You'll also need to change connection_handler
to take void*
instead of int
:
void *connection_handler(void* arg)
{
intptr_t connection_fd = (intptr_t)arg;
...
}
Upvotes: 3
Reputation: 36402
Your usage of pthread_create
is incorrect. the third argument should be a pointer to a function of type void *(*start_routine) (void *)
, instead you are passing the return of connection_handler
.
Change connection_handler
to receive a void *
argument (and make sure it returns an actual value), eg.
#include <stdint.h>
void *connection_handler(void *arg)
{
intptr_t connection_fd = (intptr_t)arg;
...
return NULL;
}
and change your call to something like the following
pthread_create(&thread, NULL, &connection_handler, (void *)conn_fd);
You should also make sure to either start the thread detached, detach the thread with pthread_detach
or join it later with pthread_join
Upvotes: 1
Reputation: 4245
Most likely because you are closing the socket connection in two places. There is good chance that in one run of the thread its not yet got around to the write
but in your parent thread already closed the connection.
Why do you need to create so many threads? Wouldn't one worker thread suffice? you can pile up the jobs on to this worker thread...
Upvotes: 0
Reputation: 96266
buffer[nbytes] = 0;
This will overflow if you've read 256 bytes. Increase buffer size or decrease read size by one.
Upvotes: 0