我在same situation as this guy,但我不太明白答案。
问题:
accept
。close
。解决方案:
你应该做的是向阻塞的线程发送信号 接受。这将给它EINTR,它可以干净地脱离 - 和 然后关闭套接字。不要从一个以外的线程中关闭它 使用它。
我不知道该怎么做 - 当在线程1中收到信号时,accept
已经阻塞,并且在信号处理程序完成后将继续阻塞。
accept
立即返回的事情,为什么线程2在没有信号的情况下也不能这样做?答案 0 :(得分:5)
而不是在accept()
中阻止,阻止select()
,poll()
或其中一个允许您等待多个文件描述符上的活动并使用“自我”的类似调用管道技巧“。传递给select()
的所有文件描述符都应该处于非阻塞模式。其中一个文件描述符应该是与accept()
一起使用的服务器套接字;如果那个变得可读,那么你应该继续调用accept()
并且它不会阻止。除此之外,创建一个pipe()
,将其设置为非阻塞,并检查读取端是否可读。而不是在另一个线程中的服务器套接字上调用close()
,而是将一个字节的数据发送到管道写入端的第一个线程。实际的字节值无关紧要;目的只是唤醒第一个线程。当select()
指示管道可读时,read()
并忽略管道中的数据,close()
服务器套接字,并停止等待新连接。
答案 1 :(得分:2)
如果在接受连接之前捕获到信号,则accept()调用将返回错误代码EINTR。因此,请检查返回值和错误代码,然后相应地关闭套接字。
如果您希望完全避免使用信号机制,请在调用accept()之前使用select()确定是否有可接受的传入连接。可以使用超时进行select()调用,以便您可以恢复并响应中止条件。
我通常在检查退出/中止条件的while循环中调用select(),其超时为1000到3000毫秒。如果select()返回一个就绪描述符,我会调用accept(),否则我会循环并在select()上再次阻塞,或者在请求时退出。
答案 2 :(得分:0)
只需关闭侦听套接字,并从accept()处理生成的错误或异常。
答案 3 :(得分:0)
从线程2调用shutdown()。accept
将返回“无效参数”。
这似乎有效,但文档并没有真正解释它在线程之间的操作 - 它似乎只是起作用 - 所以如果有人能澄清这一点,我会接受这个作为答案。
答案 4 :(得分:0)
我相信信号可以在不增加图书馆警告的情况下使用#34;。请考虑以下事项:
#include <pthread.h>
#include <signal.h>
#include <stddef.h>
static pthread_t thread;
static volatile sig_atomic_t sigCount;
/**
* Executes a concurrent task. Called by `pthread_create()`..
*/
static void* startTask(void* arg)
{
for (;;) {
// calls to `select()`, `accept()`, `read()`, etc.
}
return NULL;
}
/**
* Starts concurrent task. Doesn't return until the task completes.
*/
void start()
{
(void)pthread_create(&thread, NULL, startTask, NULL);
(void)pthread_join(thread);
}
static void noop(const int sig)
{
sigCount++;
}
/**
* Stops concurrent task. Causes `start()` to return.
*/
void stop()
{
struct sigaction oldAction;
struct sigaction newAction;
(void)sigemptyset(&newAction.sa_mask);
newAction.sa_flags = 0;
newAction.sa_handler = noop;
(void)sigaction(SIGTERM, &newAction, &oldAction);
(void)pthread_kill(thread, SIGTERM); // system calls return with EINTR
(void)sigaction(SIGTERM, &oldAction, NULL); // restores previous handling
if (sigCount > 1) // externally-generated SIGTERM was received
oldAction.sa_handler(SIGTERM); // call previous handler
sigCount = 0;
}
这具有以下优点:
pthread_cancel()
,pthread_cleanup_push()
,pthread_cleanup_pop()
和pthread_setcancelstate()
更容易推断资源泄漏。