2013-09-21 5 views
24

나는 posix 소켓을 기반으로 클라이언트 프로그램을 작성한다. 프로그램은 여러 스레드를 작성하고 서버를 잠글 것입니다. 그러나, GDB 시간 디버그 동안 프로그램 (오류) "(GDB) N프로그램 수신 신호 SIGPIPE, 파손 된 파이프.?

프로그램 신호 SIGPIPE 깨진 파이프. __kernel_vsyscall에 0xb7fdd424() ([ 0xb74c0b40 (LWP 4864) 스레드 스위칭] 통해 들어온 정보 제공 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; 
} 

입니까?

답변

30

이 프로세스는 SIGPIPE을 수신했습니다. 이 신호의 기본 동작은 프로세스를 종료하는 것입니다.

SIGPIPE은 쓰기를 위해 종료되었거나 연결되지 않은 (더 이상) 소켓에 쓰려고하면 프로세스로 전송됩니다.

프로그램이이 경우에 끝나는 것을 방지하기 위해, 당신도

  • 는 (일반적으로 아무것도하지 않고) 프로세스가 SIGPIPE 또는
  • SIGPIPE에 대한 명시 적 처리기를 설치 무시 만들 수 있습니다. 두 경우 모두 send*()/ write()에서

-1을 반환하고 EPIPEerrno을 설정합니다.

+0

이 방법이 유용할까요? if (signal (SIGPIPE, signalHandler) == EINVAL) 어떻게 -1과 EPIPE 오류가 발생합니까? – jongbanaag

+0

@ Dreyfus15 : 신호 처리기를 세우는 방법에 대한 불확실성을 명확히하기 위해 이것에 대한 또 다른 질문을 게시하십시오. – alk

3

피어에 의해 이미 닫힌 연결에 기록했습니다.

13

SIGPIPE에 대한 해결 방법,이 코드에 의해이 신호를 무시할 수 있습니다 : (세계적으로 주 또는)

#include <signal.h> 

/* Catch Signal Handler functio */ 
void signal_callback_handler(int signum){ 

     printf("Caught signal SIGPIPE %d\n",signum); 
} 
코드에서

/* Catch Signal Handler SIGPIPE */ 
signal(SIGPIPE, signal_callback_handler); 
+6

SIGPIPE 용 신호 처리기가 메시지를 stdout에 씁니다. 하지만 stdout에 글을 쓰면 처음에는 SIGPIPE가 발생했습니다 ...? – tetsujin

+1

시그널 핸들러의 non-reentrant stdio를 사용하는 것은 안전하지 않습니다. – ulix

13

'을 GDB'로 디버깅 할 때, 그것은 가능하다 다음과 같이 수동으로 SIGPIPE를 비활성화 :

특급의

은 (GDB) 처리 SIGPIPE의 nostop

2

I 종류 같은 문제를 극복하고 그것은이 게시물로 나를 보자. 나는 간헐적 인 SIGPIPE 신호로 인해 fastcgi C 프로그램의 충돌이 nginx에 의해 발생했다. 나는 행운없이 signal(SIGPIPE, SIG_IGN);에 노력했다, 그것은 부서지는 것을 유지했다.

그 이유는 nginx의 임시 디렉토리에 권한 문제가 있기 때문입니다. 권한을 수정하면 SIGPIPE 문제가 해결되었습니다. Details here on how to fixmore here.

관련 문제