Programmempfangssignal SIGPIPE, Rohrbruch

Lesezeit: 4 Minuten

Ich schreibe ein Client-Programm, das auf Posix-Sockets basiert. Das Programm erstellt mehrere Threads und wird den Server sperren. Aber während des Debuggens in gdb-Zeit gibt das Programm eine Info (Fehler)

(gdb) n
Program received signal SIGPIPE, Broken pipe. [Switching to Thread 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 ist das und was ist zu tun?

  • Mögliches Duplikat von Wie man SIGPIPEs verhindert (oder richtig damit umgeht)

    – iammilind

    14. Mai 2019 um 7:22 Uhr

Benutzeravatar von alk
alk

Der Prozess erhielt a SIGPIPE. Das Standardverhalten für dieses Signal ist das Beenden des Prozesses.

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

Um zu vermeiden, dass das Programm in diesem Fall beendet wird, können Sie beides tun

  • Lassen Sie den Prozess ignorieren SIGPIPE

    #include <signal.h>
    
    int main(void)
    {
      sigaction(SIGPIPE, &(struct sigaction){SIG_IGN}, NULL);
    
      ...
    

    oder

  • Installieren Sie einen expliziten Handler für SIGPIPE (normalerweise nichts tun):

    #include <signal.h>
    
    void sigpipe_handler(int unused)
    {
    }
    
    int main(void)
    {
      sigaction(SIGPIPE, &(struct sigaction){sigpipe_handler}, NULL);
    
      ...
    

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

  • würde das funktionieren? if(signal(SIGPIPE, signalHandler) == EINVAL) wie würde ich den Fehler -1 und EPIPE bekommen.

    – n0min

    3. Oktober 2013 um 8:11 Uhr

  • @Dreyfus15: Um Unsicherheiten bezüglich der Einrichtung von Signalhandlern zu klären, posten Sie bitte eine weitere Frage dazu.

    – alk

    4. Oktober 2013 um 5:58 Uhr

Beim Debuggen mit ‘gdb’ ist es möglich, SIGPIPE wie folgt manuell zu deaktivieren:

(gdb) behandelt SIGPIPE nostop

  • Es ist eigentlich handle SIGPIPE nostop noprint pass

    – Treviño

    20. November 2018 um 0:56 Uhr

  • Dadurch wird das Programm beendet, anstatt in gdb anzuhalten (es sei denn, das Programm ignoriert SIGPIPE oder installiert einen Handler dafür, gemäß der akzeptierten Antwort).

    – Carlo Holz

    30. Juni 2019 um 18:14 Uhr

Benutzeravatar von Hatem Mashaqi
Hatem Mashaqi

Eine Problemumgehung für SIGPIPE, Sie können dieses Signal mit diesem 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);

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

    – tetsujin

    28. Februar 2017 um 19:22 Uhr

  • Die Verwendung von nicht wiedereintrittsfähigem stdio von Signal-Handlern ist nicht sicher.

    – ulix

    21. Oktober 2017 um 7:47 Uhr

  • Es ist wahr, dass Sie sich Gedanken über wiedereintretenden Code machen müssen, wenn Sie im Handler ein printf() ausführen. Da es sich jedoch nur um ein Beispiel handelt, ist ein printf () in Ordnung. Geben Sie einfach ein Signal aus (SIGPIPE, SIG_DFL); vor dem printf () und Sie sollten in Ordnung sein.

    – Paul Hutchinson

    15. August 2020 um 23:25 Uhr


Sie haben auf eine bereits vom Peer geschlossene Verbindung geschrieben.

Benutzeravatar von neoneye
Neonauge

Ich hatte irgendwie das gleiche Problem und es hat mich zu diesem SO-Post geführt. Ich habe sporadische SIGPIPE-Signale erhalten, die zu Abstürzen meines Fastcgi-C-Programms führten, das von nginx ausgeführt wird. Ich versuchte zu signal(SIGPIPE, SIG_IGN); ohne Glück, es stürzte immer wieder ab.

Der Grund war, dass das temporäre Verzeichnis von nginx ein Berechtigungsproblem hatte. Das Korrigieren der Berechtigungen löste das SIGPIPE-Problem. Details zur Behebung hier und mehr hier.

1407550cookie-checkProgrammempfangssignal SIGPIPE, Rohrbruch

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy