2013-09-21 18 views
24

Scrivo un programma client basato su socket posix. Il programma crea più thread e bloccherà il server. Ma durante il debug in tempo gdb il programma dà un info (errore) "(gdb) nSegnale di ricezione programma SIGPIPE, Tubo rotto.?

programma ha ricevuto il segnale SIGPIPE, tubo rotto. [Il passaggio a Far passare 0xb74c0b40 (LWP 4864)] 0xb7fdd424 in __kernel_vsyscall() (gdb) "

ecco il codice

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

che cosa è e che cosa fare?

risposta

30

Il processo ha ricevuto un SIGPIPE. Il comportamento predefinito per questo segnale è terminare il processo.

Un SIGPIPE viene inviato a un processo se ha tentato di scrivere su un socket che era stato arrestato per la scrittura o non è più connesso.

Per evitare che il programma si conclude in questo caso, si potrebbe o

  • rendere il processo di ignorare SIGPIPE o
  • installare un gestore esplicita per SIGPIPE (in genere non fare nulla).

In entrambi i casi send*()/write() sarebbero tornati -1 e impostare errno-EPIPE.

+0

sarebbe questo lavoro? if (segnale (SIGPIPE, signalHandler) == EINVAL) come si ottiene l'errore -1 e EPIPE. – jongbanaag

+0

@ Dreyfus15: per chiarire le incertezze su come radunare i gestori di segnali, si prega di inviare un'altra domanda al riguardo. – alk

3

È stato scritto su una connessione che è già stata chiusa dal peer.

13

Una soluzione per SIGPIPE, è possibile ignorare questo segnale da questo codice:

#include <signal.h> 

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

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

nel codice (principale o globalmente)

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

Il gestore del segnale per SIGPIPE scrive un messaggio su stdout. Ma supponiamo che scrivere su stdout sia ciò che ha causato SIGPIPE in primo luogo ...? – tetsujin

+1

L'utilizzo di stdio non rientranti dai gestori di segnale non è sicuro. – ulix

13

Quando il debug con 'gdb', è possibile disabilitare manualmente SIGPIPE come segue:

(gdb) gestire SIGPIPE nostop

2

I sorta di exp Erientato lo stesso problema e mi ha lasciato a questo post SO. Ho ricevuto sporadici segnali SIGPIPE che causavano arresti anomali del mio programma fastcgi C eseguito da nginx. Ho provato a signal(SIGPIPE, SIG_IGN); senza fortuna, continuava a schiantarsi.

La ragione era che la dir temp di nginx aveva un problema di autorizzazione. La correzione delle autorizzazioni ha risolto il problema SIGPIPE. Details here on how to fix e more here.

Problemi correlati