Paw*_*lov 4 linux pthreads file-descriptor
如果我有两个线程(Linux、NPTL),并且我有一个线程轮询一个或多个文件描述符,而另一个线程正在关闭其中一个,这是一个合理的操作吗?我在做一些我不应该在 MT 环境中做的事情吗?
我考虑这样做的主要原因是,我不一定要与轮询线程通信,中断它等,我只想出于任何原因关闭描述符,当轮询线程唤醒时,我希望 revents 包含 POLLNVAL,这表明文件描述符应该在下一次轮询之前被线程丢弃。
我已经进行了一个简单的测试,它确实表明 POLLNVAL 正是将要发生的事情。但是,在这种情况下,POLLNVAL 仅在超时到期时设置,关闭套接字似乎不会使 poll() 返回。如果是这种情况,我可以终止线程以使 poll() 重新启动以返回。
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <poll.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
static pthread_t main_thread;
void * close_some(void*a) {
printf("thread #2 (%d) is sleeping\n", getpid());
sleep(2);
close(0);
printf("socket closed\n");
// comment out the next line to not forcefully interrupt
pthread_kill(main_thread, SIGUSR1);
return 0;
}
void on_sig(int s) {
printf("signal recieved\n");
}
int main(int argc, char ** argv) {
pthread_t two;
struct pollfd pfd;
int rc;
struct sigaction act;
act.sa_handler = on_sig;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGUSR1, &act, 0);
main_thread = pthread_self();
pthread_create(&two, 0, close_some, 0);
pfd.fd = 0;
pfd.events = POLLIN | POLLRDHUP;
printf("thread 0 (%d) polling\n", getpid());
rc = poll(&pfd, 1, 7000);
if (rc < 0) {
printf("error : %s\n", strerror(errno));
} else if (!rc) {
printf("time out!\n");
} else {
printf("revents = %x\n", pfd.revents);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
至少对于 Linux,这似乎是有风险的。close警告的手册页:
关闭文件描述符可能是不明智的,因为它们可能正被同一进程中的其他线程中的系统调用使用。由于文件描述符可能会被重用,因此有一些模糊的竞争条件可能会导致意外的副作用。
由于您使用的是 Linux,您可以执行以下操作:
eventfd并将其添加到投票中eventfd当你想关闭一个 fd 时发出信号(写入它)eventfd您可以立即关闭一个 fd 并将其从poll或者,您可以简单地建立一个signal处理程序并检查errno == EINTR何时poll返回。信号处理程序只需要将一些全局变量设置为您要关闭的 fd 的值。
既然你是在Linux上,你可能要考虑epoll为上级尽管非标准的替代品poll。
| 归档时间: |
|
| 查看次数: |
4554 次 |
| 最近记录: |