gpt4 book ai didi

c - 异步信号导致套接字 I/O 问题

转载 作者:行者123 更新时间:2023-11-30 17:59:05 26 4
gpt4 key购买 nike

我正在多线程环境中开发客户端-服务器应用程序。客户端和服务器都有两个线程。主线程使用套接字(IPv4-TCP)发送数据,客户端相应的主线程接收数据发送和接收函数是自定义函数,作为我设计的一部分。我在另一个线程中为服务器上的 SIGUSR1、SIGUSR2 和 SIGINT 设置了三个信号处理程序。在接收 SIGINT 时,会进行线程清理以正常关闭所有套接字并终止线程,而在接收 SIGUSR1,SIGUSR2 时,我设置了两个全局标志,它们在同一线程中使用,并在主线程中的自定义发送函数中执行一些操作将套接字id切换到IPv6的操作。(有逻辑让客户端知道套接字已更改为IPv6)。自定义发送/接收函数有 malloc 和 free 函数。

问题是当我在终端上使用kill -SIGUSR1 pid向服务器进程发送信号时,在一些发送调用之后,传输挂起。对于每个发送调用,我正在发送数据包,该数据包具有要发送的数据大小,实际数据和一个可选标志,指示下一个数据将位于另一个套接字 ID 上。当我在客户端打印数据大小时,在收到信号后进行某些recv调用后,数据大小全为零。我确信信号必须是原因,因为当我反转操作并让客户端将数据发送到服务器(上传)时使用相同的发送/接收功能,它工作正常。我可以切换套接字 ID。在这两种情况下,我都会向服务器进程发送信号。由于 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;
}

最佳答案

感谢大家的回复。经过进一步研究,我发现 SIGUSR1 是由主线程处理的,而不是控制线程。由于调用的 fn_recv 具有像 malloc、free 这样的函数,我认为这些函数是不可重入的,所以它导致了问题。

我通过屏蔽 SIGUSR1 信号并创建一个单独的线程来设置信号处理程序而不是控制线程来解决它,以避免干扰系统/函数调用。我在新线程中取消屏蔽 SIGUSR1 信号,以确保它仅由该新线程处理。我现在能够多次传输数据并切换套接字 ID,而不会出现停顿。如果有人需要更多详细信息,请告诉我。 基本上在主线程中屏蔽信号并在子线程中取消它就可以了!

关于c - 异步信号导致套接字 I/O 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11753229/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com