C - 发信号到另一个线程进行清理并退出

时间:2014-06-07 05:03:57

标签: c sockets pthreads signals

这不是一个家庭作业问题,我保证。

我正在编写一个时间序列数据库实现作为学习C的方法。

我有一个我写过的客户/服务器对。服务器当前是侦听端口上的套接字的echo服务器。客户端连接到该端口并向其发送输入行。它使用readline来获取输入,send到客户端套接字,recv是来自客户端套接字的一行,并将该行打印到终端。冲洗,重复。客户端从EOF获得recv时返回,此时它知道连接已关闭。

问题是readline正在阻止,这样如果服务器进程被终止,即我SIGINT,则客户端仍然在readline上阻塞。直到send之后,recvEOF,它才知道服务器已经消失。

想要发生的事情是,如果EOF上有recv并立即退出,客户就会收到信号。

我认为我需要做的是为网络客户端(pthreadssend)创建3 recv - 2,为终端创建1 。终端呼叫readline并阻止。它接受输入,然后使用pthread_cond_t发信号通知等待网络客户端send线程发送。网络客户端recv线程始终recv,这将阻止。如果它是EOF,它会引发SIGINTpthread_kill所有3个线程的处理程序,fprintf类似于"连接由服务器关闭。& #34;,然后调用exit(是的,我知道exit会终止所有线程 - 这是一个清洁工作,看看我是否理解C)。

这是适当的方法吗?显然,网络客户终端一直这样做。什么是正确的方法?

2 个答案:

答案 0 :(得分:1)

如果我正确理解您,您希望在服务器终止时readline / write()之前的send()期间退出。你的方法很好。如果服务器已经死亡,您唯一可以捕获的方法是当您尝试write() / send()时,您将获得一个SIGPIPE,这将导致服务器立即退出。因为默认情况下,除非有数据要发送或确认,否则不会在连接上发送数据包。因此,如果您只是等待来自对等方的数据,则无法判断对等方是否已经悄然消失,或者还没有准备好发送/接收更多数据。因此,您需要在单独的线程中为SIGPIPE设置一些轮询器,并在获得它时退出。您可以使用此readline函数来帮助您开始检查。

/**
 * Simple utility function that reads a line from a file descriptor fd, 
 * up to maxlen bytes -- ripped from Unix Network Programming, Stevens.
 */
int
readline(int fd, char *buf, int maxlen)
{
    int n, rc;
    char c;

    for (n = 1; n < maxlen; n++) {
    if ((rc = read(fd, &c, 1)) == 1) {
        *buf++ = c;
        if (c == '\n')
        break;
    } else if (rc == 0) {
        if (n == 1)
        return 0; // EOF, no data read
        else
        break; // EOF, read some data
    } else
        return -1; // error
    }

    *buf = '\0'; // null-terminate
    return n;
}

答案 1 :(得分:1)

之前已经回答过这个问题。我得到了Stevens,第5章建议将readline调用与套接字read交错以查找EOF。我对libreadlineselect / poll进行了Google搜索,并看到了这一点:

Interrupting c/c++ readline with signals

有一种方法可以使用交错I / O,因此libreadline不会阻止:

http://www.delorie.com/gnu/docs/readline/rlman_41.html

感谢@ arayq2和@ G--建议史蒂文斯!