- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
之前我问过question关于如何终止因 I/O 而阻塞的线程。考虑到一些优点,我使用了 pthread_kill()
而不是 pthread_cancel()
或写入管道。
我已经实现了使用 pthread_kill()
向目标线程发送信号 (SIGUSR2) 的代码。下面是这个的框架代码。大多数情况下,getTimeRemainedForNextEvent()
会返回一个阻止 poll() 数小时的值。由于这个较大的超时值,即使 Thread2 设置了 terminateFlag(以停止 Thread1),Thread2 也会被阻塞,直到 Thread1 的 poll() 返回(如果套接字上没有事件,这可能会在几个小时后)。因此,我使用 pthread_kill()
向 Thread1 发送信号以中断 poll() 系统调用(如果它被阻止)。
static void signalHandler(int signum) {
//Does nothing
}
// Thread 1 (Does I/O operations and handles scheduler events).
void* Thread1(void* args) {
terminateFlag = 0;
while(!terminateFlag) {
int millis = getTimeRemainedForNextEvent(); //calculate maximum number of milliseconds poll() can block.
int ret = poll(fds,numOfFDs,millis);
if(ret > 0) {
//handle socket events.
} else if (ret < 0) {
if(errno == EINTR)
perror("Poll Error");
break;
}
handleEvent();
}
}
// Thread 2 (Terminates Thread 1 when Thread 1 needs to be terminated)
void* Thread2(void* args) {
while(1) {
/* Do other stuff */
if(terminateThread1) {
terminateFlag = 1;
pthread_kill(ftid,SIGUSR2); //ftid is pthread_t variable of Thread1
pthread_join( ftid, NULL );
}
}
/* Do other stuff */
}
如果 Thread2 在 poll() 系统调用中阻塞时设置 terminateFlag 并向 Thread1 发送信号,则上面的代码可以正常工作。但是,如果上下文切换发生在 Thread1 的 getTimeRemainedForNextEvent()
函数之后,并且 Thread2 设置了 terminateFlag 并发送信号,则 Thread1 的 poll() 会被阻塞几个小时,因为它丢失了中断系统调用的信号。
看来我不能使用互斥量进行同步,因为 poll() 将持有锁直到它被解锁。我可以应用任何同步机制来避免上述问题吗?
最佳答案
首先,多线程访问共享变量terminateFlag
must受到互斥锁或类似同步机制的保护,否则您的程序不符合要求并且所有赌注都将关闭。例如,这可能看起来像这样:
void *Thread1(void *args) {
pthread_mutex_lock(&a_mutex);
terminateFlag = 0;
while(!terminateFlag) {
pthread_mutex_unlock(&a_mutex);
// ...
pthread_mutex_lock(&a_mutex);
}
pthread_mutex_unlock(&a_mutex);
}
void* Thread2(void* args) {
// ...
if (terminateThread1) {
pthread_mutex_lock(&a_mutex);
terminateFlag = 1;
pthread_mutex_unlock(&a_mutex);
pthread_kill(ftid,SIGUSR2); //ftid is pthread_t variable of Thread1
pthread_join( ftid, NULL );
}
// ...
}
但这并没有解决主要问题,线程 2 发送的信号可能会在测试 terminateFlag
之后但在调用 之前传递给线程 1 poll()
,尽管它确实缩小了可能发生这种情况的窗口。
最干净的解决方案是@PaulSanders 的回答已经建议的:让线程 2 通过线程 1 正在轮询的文件描述符唤醒线程 1(即通过管道)。然而,由于您似乎有合理的理由寻求替代方法,因此也应该可以通过适当使用信号屏蔽来使您的信号方法起作用。扩展@Shawn 的评论,以下是它的工作原理:
父线程在启动线程 1 之前阻塞 SIGUSR2
,因此从其父线程继承其信号掩码的线程 1 从阻塞的信号开始。
线程 1 使用 ppoll()
而不是 poll()
,以便能够指定 SIGUSR2
将是在通话期间畅通无阻。 ppoll()
以原子方式处理信号掩码,因此当信号在调用之前被阻塞并在调用中解除阻塞时,信号不会丢失。
线程 2 使用 pthread_kill()
向线程 1 发送 SIGUSR2
使其停止。因为该信号只有在执行 ppoll()
调用时才会为该线程解除阻塞,所以它不会丢失(阻塞的信号在解除阻塞之前保持挂起状态)。 ppoll()
正是为这种使用场景而设计的。
您甚至应该能够取消 terminateThread
变量和关联的同步,因为您应该能够依赖 ppoll()< 期间传递的信号
调用并因此导致执行 EINTR
代码路径。该路径不依赖于 terminateThread
来使线程停止。
关于c++ - 使用 pthread_kill() 终止因 I/O 而阻塞的线程的同步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53282566/
我想确定一个特定的线程是否“存在”。 pthread_kill()似乎适合这项任务,至少根据其 man page . If sig is 0, then no signal is sent, but
问题非常简单:我的应用程序在 32 位架构上完美运行,但在 64 位架构上运行。我遇到段错误。我猜原因是执行了 pthread_kill() 调用。这是可能的还是我的假设是错误的? 最佳答案 这里有一
为什么这个线程在我杀了它之后还继续执行?? pthread_t pid; pthread_create(&pid, NULL, (func)countdown, NULL); pthread_kill
我正在使用 int s=pthread_kill(thread_arr[t], 9); 将 SIGKILL 信号发送到位于 thread_arr t 位置的线程,而不是杀死这个确切的线程我的整个程序都
GDB 告诉我 pthread_kill 导致我的程序出现段错误。基本上,我使用 pthread_kill 来检查线程是否处于事件状态或未提供其 ID。 我一直在网上搜索,发现可能是 pthread_
我有以下崩溃报告,但我无法找出此崩溃的原因。这种崩溃经常出现,但每次的模式都不同。非常感谢! Thread 0 Crashed: 0 libsystem_kernel.dylib 0x00000001
我读到 WinAPI 中的 TerminateThread() 使用起来很危险。 在 Linux 中使用 pthread_kill() 也有危险吗? 编辑:抱歉,我指的是 pthread_kill()
信号可以在任何线程或主程序本身中接收。我从主程序创建了一个辅助线程。所以我的程序中有两个线程 1. 主线程(进程本身) 2. 辅助线程。我只希望每当信号到达我的辅助线程时,它应该向我的主线程(程序)发
我对 pthread_kill() 行为有疑问。 这是我正在尝试的一个小代码: void my_handler1(int sig) { printf("my_handle1: Got sign
什么时候用pthread_cancel而不是 pthread_kill ? 最佳答案 我不会使用这两个,但这只是个人喜好。 两者中, pthread_cancel 是终止线程最安全的方法,因为该线程只
我正在尝试使用pthread_kill向特定线程发送信号。我使用 pthread_from_mach_thread_np() 获取句柄,然后使用 pthread_kill 发送信号。 这在我的其他测试
我正在尝试使用pthread_kill向特定线程发送信号。我使用 pthread_from_mach_thread_np() 获取句柄,然后使用 pthread_kill 发送信号。 这在我的其他测试
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 5 年前。 Improve
我想使用 pthread_kill api 从主线程向子线程发送信号 (SIGUSR1),但它给出了段错误。以前我使用 2.6.20 内核版本和 gcc 4.2.1 eglbc 2.5 multili
如何使用 C++ 线程模拟 pthread_kill() 函数?我早些时候问了一个关于这个的问题,但没有得到回应。 thread::native_handle() 函数在这里有帮助吗? 最佳答案 所以
我正在制作一个小项目,该项目将被合并到更大的项目中。基本上它所做的是通过将线程添加到主结构来跟踪创建的线程,主结构跟踪线程的作用(其主要功能)及其 pthread_t id。另一个结构跟踪要传递给函数
OpenGroup Unix 规范 claims pthread_kill() 是异步信号安全的。但是 Linux man 7 signal没有在相关部分列出此功能。 那么,在 Linux 上的信号处
此请求与 PThreads 以及使用条件或信号来暂停/恢复连续循环工作线程有关。 不久前,我遇到了这个问题: https://stackoverflow.com/a/23945651/6421961
我想知道我从 Crashlytics 收到的以下堆栈跟踪中是否有任何我应该关注的内容: EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x000000007becbeb
之前我问过question关于如何终止因 I/O 而阻塞的线程。考虑到一些优点,我使用了 pthread_kill() 而不是 pthread_cancel() 或写入管道。 我已经实现了使用 pth
我是一名优秀的程序员,十分优秀!