2016-04-15 3 views
1

Linux上でmain()と2つのpthreadが作成されたCプログラムを作成しています。 pthreadの1つでは、accept()関数を呼び出す必要があります。SA_RESTARTフラグが0に設定されていても、SIGINTが発生したときにaccept()が再開します。

私はSIGINT、SIGQUITまたはSIGTERMの受信時に呼び出されるシグナルハンドラを持っています。

私はctrl-cを押したときにaccept()関数がEINTRを返すのではなく、SA_RESTARTフラグを0にしているので、デバッグ中にprintf呼び出しを束ねて実現しました私のアプリケーションがSIGINTを捕まえることができても、accept関数はブロックされたままであり、EINTRで失敗しておらず、次のコード行に移動していないことに注意してください。ここで

void terminate (int signum) 
{ 
    terminate_program = 1; 
    printf("Terminating.\n"); 
} 

は受け入れる()呼び出しが(私が作るために無関係なものを削除しようとした作られpthreadのである:ここでは はここ

struct sigaction signal_action; 
signal_action.sa_flags = 0; // Don't restart the blocking call after it failed with EINTR 
signal_action.sa_handler = terminate; 
sigemptyset(&signal_action.sa_mask); 
sigfillset(&signal_action.sa_mask); // Block every signal during the handler is executing 
if (sigaction(SIGINT, &signal_action, NULL) < 0) { 
    perror("error handling SIGINT"); 
} 
if (sigaction(SIGTERM, &signal_action, NULL) < 0) { 
    perror("error handling SIGTERM"); 
} 
if (sigaction(SIGQUIT, &signal_action, NULL) < 0) { 
    perror("error handling SIGQUIT"); 
} 

は、シグナルハンドラである)(メイン内部の私の設定です私の質問が分かりやすい):

void* pthread_timerless_socket_tasks(void* parameter) 
{ 

    server_socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(server_socket_fd < 0) 
    { 
     perror("error creating IPv4 TCP stream socket"); 
     return (NULL); 
    } 
    printf("socket created\n"); // for debugging 
    if(fcntl(server_socket_fd, F_SETFL, 0) < 0) 
    { 
     perror("error making socket_fd blocking"); 
     close(server_socket_fd); 
     return (NULL); 
    } 

    while(!terminate_program) 
    { 
     printf("socket blocking on accept\n"); // for debugging 
     client_socket_fd = accept(server_socket_fd,(struct sockaddr *) &client_address, &client_length); 
     printf("socket accepted?\n"); // for debugging 
     if(client_socket_fd < 0) 
     { 
      perror("error accepting socket_fd"); 
      close(server_socket_fd); 
      return (NULL); 
     } 


    } 

私は自分自身を明確にしたいと思います。

これで、SA_RESTARTのLinuxマニュアルに記載されている動作を確認できないため、不足しているものや間違っているものが見つかりました。

+0

このfcntl(server_socket_fd、F_SETFL、0)...は間違っていると思われます。 – alk

+0

@alk私はファイルディスクリプタをこのようにブロックしようとしていましたが、デフォルトではそうではありませんでした。私は提案にオープンしています:) – etugcey

+0

'fcntl()'を使ってソケットのブロッキング状態を切り替える方法については、この回答をご覧ください:http://stackoverflow.com/a/1549344/694576 – alk

答えて

5

the signal(7) manual pageより:

スレッドの2つ以上がブロック解除信号がある場合、カーネルは、信号を配信するまでの任意のスレッドを選択します。

信号がacceptを実行しているスレッドに送信されない場合、その呼び出しは信号によって中断されないことを意味します。

他のすべてのスレッドのシグナルをブロック(信号マスクを設定)すると、シグナルを受信できるスレッドは、acceptを呼び出すスレッドだけです。

+0

私はmain()からaccept()を使ってスレッドに(sigactionを呼び出してsa_flagsを0に設定する) "settings"コードを移動し、シグナルが配信されていることを確認するために他のスレッドにこのコードがないことを確認しました。 ()はまだブロックしています。 – etugcey

+0

私はあなたのポストから気づいた、私は他のスレッドもブロックする必要があります、私は今それを試してみましょう。 – etugcey

+0

@etugceyリンクされたマニュアルページを開き、「信号マスクと保留信号」を検索します。これは、プロセスごとおよびスレッドごとにシグナルをブロックおよびブロック解除する必要がある機能を示します。 –

関連する問題