2013-09-21 9 views
24

Piszę program klienta oparty na gniazdach POSIX. Program tworzy wiele wątków i zamierza zablokować serwer. Ale podczas debugowania w gdb czasie program podaje informacje (błąd) „(gdb) nProgram otrzymał sygnał SIGPIPE, Broken pipe.?

Program otrzymał SIGPIPE sygnał, rury złamane. [Przełączanie wątek 0xb74c0b40 (LWP 4864)] 0xb7fdd424 w __kernel_vsyscall() (gdb) "

oto kod

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

co to jest i co robić?

Odpowiedz

30

Proces otrzymał SIGPIPE. Domyślnym zachowaniem tego sygnału jest zakończenie procesu.

A SIGPIPE jest wysyłany do procesu, jeśli próbował napisać do gniazda, które zostało zamknięte do zapisu lub nie jest już podłączone (więcej).

Aby uniknąć że program kończy się w tym przypadku można albo

  • uczynić proces ignorować SIGPIPE lub
  • zainstalować wyraźnej obsługi dla SIGPIPE (zwykle nic nie robi).

W obu przypadkach send*()/write() wróci -1 i ustawić errno do EPIPE.

+0

czy to działa? jeśli (sygnał (SIGPIPE, signalHandler) == EINVAL) jak uzyskać błąd -1 i EPIPE. – jongbanaag

+0

@ Dreyfus15: Aby wyjaśnić wątpliwości związane z obsługą sterowników sygnałów, proszę zamieścić inne pytanie na ten temat. – alk

3

Napisałeś połączenie, które zostało już zamknięte przez partnera.

13

obejście SIGPIPE można ignorować tego sygnału przez ten kod:

#include <signal.h> 

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

     printf("Caught signal SIGPIPE %d\n",signum); 
} 

w kodzie (główny lub globalnie)

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

Twoja procedura obsługi sygnału dla SIGPIPE wypisze komunikat na standardowe wyjście. Ale przypuśćmy, że pisanie do stdout jest tym, co spowodowało SIGPIPE w pierwszej kolejności ...? – tetsujin

+1

Używanie nierecentrancyjnego stdio z programów obsługi sygnałów nie jest bezpieczne. – ulix

13

Gdy debugowanie z 'gdb', możliwe jest ręczne wyłączanie SIGPIPE następująco:

(gdb) uchwyt SIGPIPE nostop

2

ja rodzaj exp ominął ten sam problem i pozwolił mi na to stanowisko SO. Dostałem sporadyczne sygnały SIGPIPE powodujące awarie mojego programu fastcgi C uruchamianego przez nginx. Próbowałem bez powodzenia, signal(SIGPIPE, SIG_IGN);, ciągle się zawiesza.

Powodem było to, że administrator tymczasowy nginx miał problem z uprawnieniami. Naprawienie uprawnień rozwiązało problem SIGPIPE. Details here on how to fix i more here.

Powiązane problemy