C - 带线程的神秘分割错误

时间:2011-08-02 11:19:05

标签: c multithreading sockets segmentation-fault

这是一个我正在研究的简单程序,它监听套接字,并启动一个新线程来处理与所述套接字的每个连接。 在我的while循环中,我得到一个分段错误,它与pthread_create有关(如果我注释掉该程序循环正确)。我对指针的了解充其量只是平庸,而使用gdb进行调试并没有产生任何有价值的东西。这是gdb的输出:

#0  0x0000000000000000 in ?? ()
#1  0x000000080064f4f1 in pthread_getprio () from /lib/libthr.so.3
#2  0x0000000000000000 in ?? ()
Error accessing memory address 0x7fffffbff000: Bad address.

程序成功通过while循环,并正确接收并响应套接字上的连接,但在进入第二个while循环之前,程序在分段错误错误时失败。

这是我的程序的精简版本:

#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;
}

任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:3)

这是错误的:

pthread_create(&thread , NULL, connection_handler(conn_fd), NULL);

pthread_create要求函数的地址在新线程中运行。您的代码所做的是在主线程中调用connection_handler,然后将 connection_handler 的结果传递给pthread_create作为函数地址。

您需要的是以下内容:

pthread_create(&thread , NULL, connection_handler, (void*)conn_fd);

您还需要更改connection_handler以取消void*而不是int

void *connection_handler(void* arg)
{
  intptr_t connection_fd = (intptr_t)arg;
  ...
}

答案 1 :(得分:1)

您对pthread_create的使用不正确。第三个参数应该是指向void *(*start_routine) (void *)类型函数的指针,而不是传递connection_handler的返回值。

更改connection_handler以接收void *参数(并确保它返回实际值),例如。

#include <stdint.h>

void *connection_handler(void *arg)
{
    intptr_t connection_fd = (intptr_t)arg;
    ...
    return NULL;
}

并将您的通话更改为以下内容

pthread_create(&thread, NULL, &connection_handler, (void *)conn_fd);

您还应确保启动分离的线程,使用pthread_detach分离线程或稍后使用pthread_join

加入该线程

答案 2 :(得分:0)

buffer[nbytes] = 0;

如果您读取256个字节,则会溢出。增加缓冲区大小或将读取大小减少一个。

答案 3 :(得分:0)

最有可能的原因是你在两个地方关闭套接字连接。很有可能在线程的一次运行中它尚未到达write,但在您的父线程中已经关闭了连接。

为什么需要创建这么多线程?一个工人的线程不够用吗?你可以将这些工作堆积到这个工人线程......