35 c sockets gdb pthreads sigpipe
我写了一个基于posix套接字的客户端程序.该程序创建多个线程,并将锁定服务器.但是在gdb时间调试期间,程序会给出一个信息(错误)
Run Code Online (Sandbox Code Playgroud)(gdb) n Program received signal SIGPIPE, Broken pipe. [Switching to Thread 0xb74c0b40 (LWP 4864)] 0xb7fdd424 in __kernel_vsyscall () (gdb)
这是代码:
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int get_hostname_by_ip(char* h , char* ip)
{
struct hostent *he;
struct in_addr **addr_list;
int i;
if ((he = gethostbyname(h)) == NULL)
{
perror("gethostbyname");
return 1;
}
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++)
{
strcpy(ip , inet_ntoa(*addr_list[i]) );
return 0;
}
return 1;
}
void client(char* h, int s)
{
int fd;
struct sockaddr_in addr;
char ch[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family=AF_INET;
char* ip = new char[20];
get_hostname_by_ip(h, ip);
addr.sin_addr.s_addr=inet_addr(ip);
int port = 80;
addr.sin_port=htons(port);
if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
perror("connect error");
return;
}
while(1)
{
if(send(fd, ch, sizeof(ch), 0) < 0)
{
perror("send");
}
}
//char buffer[1024];
//if(recv(fd, &buffer, sizeof(buffer), 0) < 0)
//{
// perror("recive");
//}
//printf("nReply from Server: %s\n", buffer);
close(fd);
}
struct info
{
char* h;
int c;
};
void* thread_entry_point(void* i)
{
info* in = (info*)i;
client(in->h, in->c);
}
int main(int argc, char** argv)
{
int s = atoi(argv[2]);
pthread_t t[s];
info in = {argv[1], s};
for(int i = 0; i < s; ++i)
{
pthread_create(&t[i], NULL, thread_entry_point, (void*)&in);
}
pthread_join(t[0], NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它是什么,做什么?
alk*_*alk 46
这个过程得到了一个SIGPIPE.此信号的默认行为是结束该过程.
如果A SIGPIPE尝试写入已关闭以进行写入或未连接的套接字(已再次发送),则会将其发送到进程.
为避免程序在这种情况下结束,您也可以
使过程忽略 SIGPIPE
#include <signal.h>
int main(void)
{
sigaction(SIGPIPE, &(struct sigaction){SIG_IGN}, NULL);
...
Run Code Online (Sandbox Code Playgroud)
要么
为SIGPIPE(通常什么都不做)安装显式处理程序:
#include <signal.h>
void sigpipe_handler(int unused)
{
}
int main(void)
{
sigaction(SIGPIPE, &(struct sigaction){sigpipe_handler}, NULL);
...
Run Code Online (Sandbox Code Playgroud)在这两种情况下send*()/ write()将返回-1并设置errno为EPIPE.
小智 24
使用'gdb'进行调试时,可以手动禁用SIGPIPE,如下所示:
(gdb)处理SIGPIPE nostop
Hat*_*aqi 13
对于SIGPIPE的解决方法,您可以通过以下代码忽略此信号:
#include <signal.h>
/* Catch Signal Handler functio */
void signal_callback_handler(int signum){
printf("Caught signal SIGPIPE %d\n",signum);
}
Run Code Online (Sandbox Code Playgroud)
在您的代码中(主要或全局)
/* Catch Signal Handler SIGPIPE */
signal(SIGPIPE, signal_callback_handler);
Run Code Online (Sandbox Code Playgroud)
我也经历过同样的问题,它让我看到了这篇文章。我收到零星的 SIGPIPE 信号,导致 nginx 运行的 fastcgi C 程序崩溃。我尝试过了signal(SIGPIPE, SIG_IGN);,但没有运气,它一直崩溃。
原因是nginx的temp目录存在权限问题。修复权限解决了 SIGPIPE 问题。有关如何修复的详细信息请参见此处。