c /中断系统调用/ fork与线程

nyy*_*kki 4 c sockets fork pthreads

我发现了线程实现的问题,这对我来说很奇怪.也许有些人可以向我解释,会很棒.

我正在开发类似代理的程序,一个程序(在不同的机器上运行),它通过eth0接收数据包并通过ath0(无线)发送到另一台机器,它正在完成同样的事情.实际上我完全不确定是什么导致了我的问题,那是因为我对一切,linux和c编程都是新手.

我开始两个线程,

  • 一个是在eth0上侦听(套接字)传入的数据包并通过ath0(也是套接字)发送出去
  • 另一个线程正在监听ath0并通过eth0发送.

如果我使用线程,我会得到一个错误:

sh-2.05b# ./socketex 
Failed to send network header packet.
: Interrupted system call
Run Code Online (Sandbox Code Playgroud)

如果我使用fork(),程序按预期工作.有人可以向我解释这种行为吗?

只是为了显示发送者实现,它的代码片段是:

while(keep_going) {
    memset(&buffer[0], '\0', sizeof(buffer));

    recvlen = recvfrom(sockfd_in, buffer, BUFLEN, 0, (struct sockaddr *) &incoming, &ilen);
    if(recvlen < 0) {
        perror("something went wrong / incoming\n");
        exit(-1);
    }

    strcpy(msg, buffer);
    buflen = strlen(msg);

    sentlen = ath_sendto(sfd, &btpinfo, &addrnwh, &nwh,  buflen, msg, &selpv2, &depv);

    if(sentlen == E_ERR) {
        perror("Failed to send network header packet.\n");
        exit(-1);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我的主文件,启动线程或进程(fork)

int main(void) {

port_config pConfig;

memset(&pConfig, 0, sizeof(pConfig));
pConfig.inPort = 2002;
pConfig.outPort = 2003;

pid_t retval = fork();

if(retval == 0) {
    // child process
    pc2wsuThread((void *) &pConfig);
} else if (retval < 0) {
    perror("fork not successful\n");
} else {
    // parent process
    wsu2pcThread((void *) &pConfig);
}

/*
wint8 rc1, rc2 = 0;

pthread_t pc2wsu;
pthread_t wsu2pc;

rc1 = pthread_create(&pc2wsu, NULL, pc2wsuThread, (void *) &pConfig);
rc2 = pthread_create(&wsu2pc, NULL, wsu2pcThread, (void *) &pConfig);

if(rc1) {
    printf("error: pthread_create() is %d\n", rc1);
    return(-1);
}

if(rc2) {
    printf("error: pthread_create() is %d\n", rc2);
    return(-1);
}

pthread_join(pc2wsu, NULL);
pthread_join(wsu2pc, NULL);
*/
return 0;
}
Run Code Online (Sandbox Code Playgroud)

有帮助吗?

更新 05/30/2011

-sh-2.05b# ./wsuproxy 192.168.1.100
mgmtsrvc
mgmtsrvc
Failed to send network header packet.
: Interrupted system call
13.254158,75.165482,DATAAAAAAmgmtsrvc
mgmtsrvc
mgmtsrvc
Run Code Online (Sandbox Code Playgroud)

仍然可以获得中断的系统调用,如上所示.我阻止了所有信号如下:

sigset_t signal_mask;
sigfillset(&signal_mask);
sigprocmask(SIG_BLOCK, &signal_mask, NULL);
Run Code Online (Sandbox Code Playgroud)

这两个线程在相同的接口上工作,但在不同的端口上.问题似乎仍然出现在同一个地方(请在第一个代码段中找到它).我不能再进一步了解如何解决这个问题.也许你们中的一些人可以再次帮助我.

提前致谢.

Mat*_*Mat 6

EINTR本身并不表示错误.这意味着你的进程在sendto系统调用时收到了一个信号,而且系统调用还没有发送任何数据(这很重要).

在这种情况下你可以重试发送,但好的方法是找出导致中断的信号.如果这是可重现的,请尝试使用strace.

如果你是发送信号的人,那么,你知道该怎么做:-)

需要注意的是在Linux上,您可以收到EINTRsendto(以及其他一些功能),即使你没有安装自己的处理程序.如果:

  • 进程停止(例如通过SIGSTOP)并重新启动(使用SIGCONT)
  • 你已经在套接字上设置了发送超时(通过SO_SNDTIMEO)

    有关signal(7)更多详细信息,请参见手册页(位于最底部).

    因此,如果您"暂停"您的服务(或其他内容),那EINTR是预期的,您应该重新启动呼叫.