2013-09-21 1 views
24

Я пишу клиентскую программу на основе сокетов posix. Программа создает несколько потоков и собирается заблокировать сервер. Но во время отладки в GDB время программа дает информацию (ошибка) «(GDB) пЗапрограммированный сигнал SIGPIPE, Broken pipe.?

Программа получила сигнал SIGPIPE, Сломанная труба. [Переключение на тему 0xb74c0b40 (LWP 4864)] 0xb7fdd424 в __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; 
} 

что это такое и что делать?

ответ

30

Процесс получил SIGPIPE. Поведение по умолчанию для этого сигнала - это завершение процесса.

A SIGPIPE отправляется процессу, если он пытался записать в сокет, который был выключен для записи или не подключен (больше).

Чтобы избежать этого, программа завершается в этом случае вы можете либо

  • сделать процесс игнорировать SIGPIPE или
  • установить явный обработчик SIGPIPE (как правило, ничего не делая).

В обоих случаях send*()/write() вернется -1 и установить errno в EPIPE.

+0

будет ли это работать? if (сигнал (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 - это то, что вызвало SIGPIPE в первую очередь ...? – tetsujin

+1

Использование не реентерабельного stdio из обработчиков сигналов небезопасно. – ulix

13

При отладке с 'GDB', можно вручную отключить SIGPIPE следующим образом:

(GDB) рукоятка SIGPIPE nostop

2

I рода ехр вызвал ту же проблему, и это позволило мне на эту должность. Я получил спорадические сигналы SIGPIPE, вызывающие сбои моей программы fastcgi C, выполняемой nginx. Я старался signal(SIGPIPE, SIG_IGN); без везения, он все время рушился.

Причина заключалась в том, что у temp dir nginx была проблема с разрешением. При фиксации разрешений была решена проблема SIGPIPE. Details here on how to fix и more here.