2013-09-21 9 views
24

私はposixソケットに基づいてクライアントプログラムを書いています。プログラムは複数のスレッドを作成し、サーバーをロックします。しかし、GDB時間のデバッグ中にプログラムが(エラー)「(GDB)のnプログラム受信信号SIGPIPE、壊れたパイプ?

プログラムは、信号SIGPIPE、壊れたパイプが。__kernel_vsyscallで0xb7fdd424()([ 0xb74c0b40(LWP 4864)スレッドへの切り替え]受け取った情報を提供します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を受け取りました。このシグナルのデフォルトの動作は、プロセスを終了することです。

SIGPIPEは、書き込みのためにシャットダウンされたソケットに接続しようとした場合、または接続されていない(それ以上の場合)プロセスに送信されます。

プログラムは、この場合に終了することを避けるために、あなたはどちらか

  • プロセスがSIGPIPEまたは
  • は(一般的に何もしない)SIGPIPEの明示的なハンドラをインストール無視することができます。どちらの場合もsend*()/write()

-1を返し、EPIPEerrnoを設定します。

+0

これは機能しますか? (signal(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に書き出します。しかし、stdoutへの書き込みが最初にSIGPIPEの原因となったとします...? – tetsujin

+1

シグナルハンドラからの非リエントラントstdioの使用は安全ではありません。 – ulix

13

'GDB' でデバッグする場合、それは可能です

を(GDB)はEXPの

2

IソートNOSTOP SIGPIPEを処理し、次のように手動SIGPIPEを無効にします同じ問題を抱えてしまいました。私は散発的なSIGPIPE信号を受けて、fastcgi Cプログラムのクラッシュをnginxによって引き起こしています。私は運が無ければsignal(SIGPIPE, SIG_IGN);にしようとしたが、クラッシュし続けた。

理由は、nginxの一時ディレクトリにアクセス権の問題があったためです。パーミッションを修正すると、SIGPIPEの問題が解決されました。 Details here on how to fixおよびmore here

関連する問題