0

マルチスレッド環境でクライアント - サーバー アプリケーションに取り組んでいます。クライアントとサーバーの両方に 2 つのスレッドがあります。メイン スレッドはソケット (IPv4-TCP) を使用してデータを送信し、クライアント側の対応するメイン スレッドはデータを受信します。 recv 関数は、私の設計の一部としてのカスタム関数です。サーバー上の SIGUSR1、SIGUSR2、および SIGINT 用に、他のスレッドに 3 つのシグナル ハンドラを設定しました。SIGINT を受信すると、すべてのソケットを適切に閉じてスレッドを終了するためにスレッドのクリーンアップが行われます。 SIGUSR1,SIGUSR2 を受信すると、同じスレッドで使用される 2 つのグローバル フラグとメイン スレッドのカスタム送信関数を設定していくつかの処理を行います。ソケット ID を IPv6 に切り替える操作 (ソケットが IPv6 に変更されたことをクライアントに知らせるロジックがあります)。カスタム送信/受信関数には、malloc 関数と free 関数があります。

問題は、端末で kill -SIGUSR1 pid を使用してサーバー プロセスにシグナルを送信するときです。いくつかの送信呼び出しの後、送信がハングします。送信呼び出しごとに、送信するデータ サイズ、実際のデータ、次のデータが別のソケット ID にあることを示すオプションのフラグ。クライアント側でデータサイズを出力すると、信号を受信した後に特定の recv 呼び出しを行った後、すべてゼロになります。操作を逆にして、クライアントにデータをサーバーに送信させる (アップロード) 場合と同様に、SIGNAL が原因であると確信しています。同じ送信/受信機能を使用すると、正常に機能します。ソケット ID を切り替えることができます。どちらの場合も、サーバープロセスにシグナルを送信しています.recv関数は、TCPがストリームベースであるため、そのパケットのサイズ部分に示されているデータ量と同じになるまでrecvします。シグナルの受信時にいくつかの送信呼び出しの後にサイズがゼロになる理由がわかりません。設定されているシグナルハンドラー部分を除いて、グローバル変数が使用される場所でミューテックスを使用しました。コードは以下の通りです。

スレッド 2:

fn_sigUsrHandler(SIGUSR1);
fn_sigUsrHandler(SIGUSR2);
fn_sigUsrHandler(SIGINT);
void fn_sigUsrHandler(int p_signal)
{
/* Signal handler structure */
struct sigaction vl_sigStruct;
int vl_errno;
char vl_err_buff[256];

vl_sigStruct.sa_flags = SA_RESTART;
sigemptyset(&vl_sigStruct.sa_mask);


switch(p_signal)
{
    case SIGUSR1:
        vl_sigStruct.sa_handler = fn_switch;
        break;
    case SIGUSR2:
        vl_sigStruct.sa_handler = fn_switch;
        break;
    case SIGINT:
        vl_sigStruct.sa_handler = fn_cleanUP;
        break;
}

vl_errno = sigaction(p_signal, &vl_sigStruct, NULL);
if (vl_errno == -1) {
    fprintf(stdout,"Control Thread-Error in catching SIGUSR1:%s\n",fn_strerror_r(errno,vl_err_buff));
    exit(EXIT_FAILURE);
}


void fn_switch(int st_val){
/*
pthread_mutex_lock(&socket_mutex_3);
ip_proto_switch = 1;
vg_ctrlpacket_sent =1;
pthread_mutex_unlock(&socket_mutex_3);
*/

vg_proto_switch = 1;
vg_ctrlpacket_sent =1;

fprintf(stdout,"Signalled to switch\n");
}

メインスレッド:

int vl_err; /* Number of bytes sents */
char err_buff[256]; /* Buffer to hold error message*/
int vl_change_sock = 0;

if(p_flags != NO_DATA_TX)
{
    char *vl_bufData;
    st_packetData vst_packet; /* Structure holding the data to be sent */
    unsigned int vl_packetSize = sizeof(unsigned int) +     sizeof(vst_packet.vst_pad) + (int)p_len;//sss
    vl_bufData = (char *)malloc(vl_packetSize);
    memset(vl_bufData,'\0',vl_packetSize);

    pthread_mutex_lock(&socket_mutex_2);
        if(vg_ctrlpacket_recv == 1){
            ///strcpy(vst_packet.vst_pad,vg_change_socket);
            vl_change_sock = 1;
            vg_ctrlpacket_recv = 0;                 
            fprintf(stdout,"len:%d\n",strlen(vst_packet.vst_pad));
        }
    pthread_mutex_unlock(&socket_mutex_2);


    if(vl_change_sock == 1){


            char *vl_bufData2 = vl_bufData+sizeof(unsigned int);
            snprintf(vl_bufData2,(int)p_len,"%s",p_buffer);
            //memcpy(vl_bufData+sizeof(unsigned int)+(int)p_len,vg_change_socket,sizeof(vst_packet.vst_pad));//sss
        */

        snprintf(vl_bufData,sizeof(unsigned int)+1,"%u",vl_packetSize);
        memcpy(vl_bufData+sizeof(unsigned int),p_buffer,(int)p_len);//sss
        snprintf(vl_bufData+sizeof(unsigned int)+(int)p_len,sizeof(vst_packet.vst_pad)+1,"%s",vg_change_socket);

        vl_err = send(p_mysocket->socket_id,vl_bufData,vl_packetSize,p_flags);
        if(vl_err == -1)
        {
            fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
            exit(EXIT_FAILURE);//HS 
        }

        if(debug > 0)
            fprintf(stdout,"The socket before change is :%d client side \n",p_mysocket->socket_id);

        if((p_mysocket->socket_id) == p_mysocket->sock_id[0])
            p_mysocket->socket_id = p_mysocket->sock_id[1];
        else
            p_mysocket->socket_id = p_mysocket->sock_id[0];

        if(debug > 0)
            fprintf(stdout,"The socket after change is :%d client side \n ",p_mysocket->socket_id);

    }
    else{
        snprintf(vl_bufData,sizeof(unsigned int)+1,"%u",vl_packetSize);
        memcpy(vl_bufData+sizeof(unsigned int),p_buffer,(int)p_len);//sss

        vl_err = send(p_mysocket->socket_id,vl_bufData,vl_packetSize,p_flags);
        if(vl_err == -1)
        {
            fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
            exit(EXIT_FAILURE);//HS 
        }

    }   

    if(debug > 2){
        /*fprintf(stdout,"size of st_packetData:%d\n",sizeof(st_packetData));
        fprintf(stdout,"vl_packetSize:%d\n",vl_packetSize); 
        fprintf(stdout,"Memcopied-data:%s\n",vst_packet.vst_data);
        fprintf(stdout,"Memcopied-pad:%s\n",vst_packet.vst_pad);
        fprintf(stdout,"Memcopied-size:%d\n",vst_packet.vst_size);//sss
        fprintf(stdout,"Data from buffer:%s\n",p_buffer);
        fprintf(stdout,"data:%s\n",vl_bufData+sizeof(vst_packet.vst_size)+sizeof(vst_packet.vst_pad));*/
        fprintf(stdout,"Copied data:%-10.6s\n",vl_bufData);
        fprintf(stdout,"---------------------------\n");
    }


    //if(vl_err >=(sizeof(vst_packet.vst_size)+ sizeof(vst_packet.vst_pad))) //sss
    if(vl_err >=(sizeof(unsigned int)+ strlen(vg_change_socket)))
    {
        vl_err = vl_err-(sizeof(unsigned int) + strlen(vg_change_socket));//sss
    }
    if(debug > 2)
    {
        fprintf(stdout,"The socket id is :%d.. Thread:%s\n",p_mysocket->socket_id,p_mysocket->vst_nm_thread);
        fprintf(stdout,"The data tx %d.. Thread:%s\n",vl_err,p_mysocket->vst_nm_thread);
    }

    free((void *)vl_bufData);

}
else
{   
    vl_err = send(p_mysocket->socket_id,p_buffer,p_len,0);
    if(vl_err == -1)
    {
        fprintf(stderr,"mysocket-fn_send-TCP-vl_err err :%s\n",fn_strerror_r(errno,err_buff));//HS
        exit(EXIT_FAILURE);//HS 
    }
    if(debug>1)
    {
        fprintf(stdout,"The socket id is :%d.. Thread:%s\n",p_mysocket->socket_id,p_mysocket->vst_nm_thread);
        fprintf(stdout,"The data tx %d.. Thread:%s\n",vl_err,p_mysocket->vst_nm_thread);
    }
}
/* return number of bytes sent */
return vl_err;
}
4

1 に答える 1

0

ご回答ありがとうございます。さらに調査を重ねた結果、SIGUSR1 は制御スレッドではなくメイン スレッドによって処理されることがわかりました。呼び出された fn_recv には malloc,free のような関数があり、再入可能ではないと思われるため、問題が発生していました。

システム/関数呼び出しとの干渉を避けるために、SIGUSR1シグナルをマスクし、制御スレッドの代わりにシグナルハンドラーを設定する別のスレッドを作成することで解決しました。新しいスレッドで SIGUSR1 シグナルのマスクを解除して、この新しいスレッドによってのみ処理されるようにしました。ストールすることなく、データを転送し、ソケット ID を複数回切り替えることができるようになりました。詳細が必要な場合はお知らせください。基本的に、メインスレッドでシグナルをマスクし、子スレッドでマスクを解除するとうまくいきました!

于 2012-08-23T18:12:12.580 に答える