这是一个我正在研究的简单程序,它监听套接字,并启动一个新线程来处理与所述套接字的每个连接。
在我的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;
}
任何帮助将不胜感激!
答案 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
,但在您的父线程中已经关闭了连接。
为什么需要创建这么多线程?一个工人的线程不够用吗?你可以将这些工作堆积到这个工人线程......