- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在做一些类(class),我们收到了以下代码。有些问题询问不同行代码的作用,这很好,我理解,但问题是“这个程序包含竞争条件。它在哪里以及为什么出现?”
代码:
#include <stdio.h>
#include <signal.h>
static void handler(int signo) {
printf("This is the SIGUSR1 signal handler!\n");
}
int main(void) {
sigset_t set;
sigemptyset(&set);
sigset(SIGUSR1, handler);
sigprocmask(SIG_SETMASK, &set, NULL);
while(1) {
printf("This is main()!\n");
}
return 0;
}
我在想,竞争条件是,当信号到达时,无法知道“This is main”或“This is the SIGUSR1”将打印什么顺序,但如果有人可以确认或澄清这一点我非常感激。他还询问如何修复它(竞争条件),而不是寻找完整的答案,但任何提示将不胜感激。
最佳答案
确实不存在竞争条件;比那更糟糕。根据 POSIX 标准,程序的行为是未定义的(如果信号在正确的时刻传递)。
查看man 7 signal手册页,特别是异步信号安全函数下的部分:
A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program. POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined.
请注意,printf()
绝对不是异步信号安全函数;因此行为是未定义的。
在一般情况下,解决方案并不简单,因为没有异步信号安全锁定原语(除了sem_post()
,它本身不足以实现此目的,并且文件锁必须在周围使用所有printf()
调用)。通用的、可移植的解决方案是使用pipe()
中的unistd.h
创建一个管道,并使用write()
将输出写入管道,然后让主程序从管道中读取并“转发”内容。写入短于PIPE_BUF
的 POSIX 保证是原子的,PIPE_BUF
至少为 512(Linux 中为 4096)——有关详细信息,请参阅 man 7 pipe
——因此在实践中这也仅限于 512 字节或更短的消息用于可移植代码。
通常,在这种特殊情况下,只需设置全局printf()
变量即可替换信号处理程序中的volatile sigatomic_t
。然后主循环可以简单地检查(并清除)全局变量并输出消息本身。
虽然标志变量方法可能会丢失快速重复的SIGUSR1
信号,但这是无关紧要的,因为您总是会丢失快速重复的SIGUSR1
信号:一次只能有一个待处理信号,因此重复在第一个信号和处理它之间发生的信号根本不会传递! (如果您要使用排队的实时信号,如SIGRTMIN+0
,您可以通过在主循环中使用原子内置信号(如__sync_fetch_and_and(variable,0)
或__atomic_exchange_n(variable,0,__ATOMIC_SEQ_CST)
,以及__sync_fetch_and_add(variable,1)
或“信号处理程序中的__atomic_fetch_add(variable,1,__ATOMIC_SEQ_CST)
;两者前面都有__sync_synchronize()
或__atomic_signal_fence(__ATOMIC_SEQ_CST)
调用,以确保更改立即生效/对另一个可见。但在这种情况下,您无需担心原子操作。)
对于sigset()
和sigprocmask()
也有一个有趣的极端情况 - 不是竞争条件。进程从其父进程继承其信号掩码,默认情况下不阻止SIGUSR1
。除非进行处理,否则它会导致进程终止。因此,根据继承的信号掩码,在SIGUSR1
调用之前传递的sigset()
信号要么被阻止,要么导致进程终止。 (但是,如果set
包含SIGUSR1
;即SIGUSR1
被阻止,那么就会出现竞争条件,除非sigprocmask()
在sigset()
之前被调用。但是,由于set
”为空,sigset()
最好在sigprocmask()
之前调用。)
关于c - C 信号处理程序中的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11816068/
我正在努力处理查询的 WHERE 部分。查询本身包含一个基于两个表中都存在的 ID 的 LEFT JOIN。但是,我要求 where 语句仅返回其中一列中存在的最大单个结果。目前我返回连接中的所有值,
我有这个代码来改变文件系统的大小。问题是,即使满足 if 条件,它也不会进入 if 条件,而我根本没有检查 if 条件。它直接进入 else 条件。 运行代码后的结果 post-install-ray
假设我有一个包含 2 列的 Excel 表格:单元格 A1 到 A10 中的日期和 B1 到 B10 中的值。 我想对五月日期的所有值求和。我有3种可能性: {=SUM((MONTH(A1:A10)=
伪代码: SELECT * FROM 'table' WHERE ('date' row.date 或 ,我们在Stack Overflow上找到一个类似的问题: https://stackove
我有下面这行代码做一个简单的查询 if ($this->fulfilled) $criteria->addCondition('fulfilled ' . (($this->fulfilled
如果在数据库中找到用户输入的键,我将尝试显示“表”中的数据。目前我已将其设置为让数据库检查 key 是否存在,如下所示: //Select all from table if a key entry
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 5 年前。 Improve th
在MYSQL中可以吗 一共有三个表 任务(task_id、task_status、...) tasks_assigned_to(ta_id、task_id、user_id) task_suggeste
我想先根据用户的状态然后根据用户名来排序我的 sql 请求。该状态由 user_type 列设置: 1=活跃,2=不活跃,3=创始人。 我会使用此请求来执行此操作,但它不起作用,因为我想在“活跃”成员
下面两个函数中最专业的代码风格是什么? 如果函数变得更复杂和更大,例如有 20 个检查怎么办? 注意:每次检查后我都需要做一些事情,所以我不能将所有内容连接到一个 if 语句中,例如: if (veh
我在 C# 项目中使用 EntityFramework 6.1.3 和 SQL Server。我有两个查询,基本上应该执行相同的操作。 1. Exams.GroupBy(x=>x.SubjectID)
我试图在 case when 语句中放入两个条件,但我在 postgresql 中遇到语法错误 case when condition 1 and condition 2 then X else Y
我正在构建一个连接多个表的查询,一个表 prodRecipe 将包含某些行的数据,但不是全部,但是 tmp_inv1 将包含所有行的计数信息。问题是,tmp_inv1.count 取决于某个项目是否在
我有一个涉及 couples of rows which have a less-than-2-hours time-difference 的查询(~0.08333 天): SELECT mt1.*,
我有一个包含许多这样的 OR 条件的代码(工作正常)来检查其中一个值是否为空,然后我们抛出一条错误消息(所有这些都必须填写) } elsif ( !$params{'account'}
我有一个名为 spGetOrders 的存储过程,它接受一些参数:@startdate 和 @enddate。这将查询“订单”表。表中的一列称为“ClosedDate”。如果订单尚未关闭,则此列将保留
在代码中,注释部分是我需要解决的问题...有没有办法在 LINQ 中编写这样的查询?我需要这个,因为我需要根据状态进行排序。 var result = ( from contact in d
我正在尝试创建一个允许省略参数的存储过程,但如果提供了参数,则进行 AND 操作: CREATE PROCEDURE MyProcedure @LastName Varchar(30)
我正在寻找一种方法来过滤我的主机文件中的新 IP 地址。我创建了一个脚本,每次我用来自矩阵企业管理器的数据调用它时都会更新我的主机文件。它工作正常。但是我必须找到一个解决方案,只允许更新 10.XX.
所以我正在做一种 slider ,当它完全向下时隐藏向下按钮,反之亦然,当向上按钮隐藏时,我遇到了问题。 var amount = $('slide').attr('number'); $('span
我是一名优秀的程序员,十分优秀!