2013-09-21 5 views
24

Ich schreibe ein Client-Programm basierend auf Posix-Sockets. Das Programm erstellt mehrere Threads und wird den Server sperren. Aber während debug in gdb Zeit gibt das Programm eine Info (Fehler) „(GDB) nProgramm empfangenes Signal SIGPIPE, Broken pipe.?

Programm empfangene Signal SIGPIPE, Zerbrochen Rohr. [Umschalten auf Gewinde 0xb74c0b40 (LWP 4864)] 0xb7fdd424 in __kernel_vsyscall() (gdb) "

hier ist der Code

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

, was es ist und was zu tun ist?

Antwort

30

Der Prozess erhielt eine SIGPIPE. Das Standardverhalten für dieses Signal besteht darin, den Prozess zu beenden.

Ein SIGPIPE wird an einen Prozess gesendet, wenn er versucht hat, in einen Socket zu schreiben, der zum Schreiben heruntergefahren wurde oder nicht mehr (mehr) angeschlossen ist.

Um zu vermeiden, dass das Programm in diesem Fall endet, Sie könnten entweder

  • machen den Prozess ignorieren SIGPIPE oder
  • für SIGPIPE einen expliziten Handler installieren (in der Regel nichts zu tun).

In beiden Fällen send*()/write() zurückkehren würde -1 und setzen errno-EPIPE.

+0

würde diese Arbeit? if (Signal (SIGPIPE, Signalhandler) == EINVAL) wie würde ich den Fehler -1 und EPIPE erhalten. – jongbanaag

+0

@ Dreyfus15: Um Unsicherheiten zu klären, wie Signal-Handler sert Sie bitte eine andere Frage zu diesem Artikel. – alk

3

Sie haben eine Verbindung geschrieben, die von der Peer bereits geschlossen worden ist.

13

Eine Abhilfe für SIGPIPE, können Sie dieses Signal durch diesen Code ignorieren:

#include <signal.h> 

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

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

in Ihrem Code (Haupt- oder global)

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

Ihr Signalhandler für SIGPIPE schreibt eine Nachricht nach stdout. Aber angenommen, das Schreiben auf stdout hat die SIGPIPE überhaupt erst verursacht ...? – tetsujin

+1

Die Verwendung von nicht-reentranten STDIO von Signalhandlern ist nicht sicher. – ulix

13

Wenn mit 'gdb' Debugging ist es möglich, manuell deaktivieren SIGPIPE wie folgt:

(gDB) hand SIGPIPE nostop

2

I Art exp Erregte das gleiche Problem und es ließ mich zu diesem SO Post. Ich bekam sporadische SIGPIPE-Signale, die zu Abstürzen meines von Nginx ausgeführten Fastcgi-C-Programms führten. Ich versuchte signal(SIGPIPE, SIG_IGN); ohne Glück, es stürzte ständig.

Der Grund dafür war, dass nginx temp dir eine Erlaubnis Problem hatte. Durch das Korrigieren der Berechtigungen wurde das SIGPIPE-Problem behoben. Details here on how to fix und more here.