【发布时间】:2020-01-31 21:35:20
【问题描述】:
总结
我尝试编写一个 Monte Carlo 模拟代码,该模拟分叉到最多数量的核心进程。在一定时间后,父级将 SIGUSR1 发送给所有子级,然后这些子级应停止计算将结果发送回父级。
当我在没有任何优化的情况下编译 (clang thread_stop.c) 时,行为符合预期。当我尝试优化代码 (clang -O1 thread_stop.c) 时,信号被捕获,但孩子们并没有停下来。
代码
我将代码缩减为行为相同的最小部分:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h> /* pid_t */
#include <sys/mman.h> /* mmap */
#define MAX 1 /* Max time to run */
static int a=0; /* int to be changed when signal arrives */
void sig_handler(int signo) {
if (signo == SIGUSR1){
a=1;
printf("signal caught\n");
}
}
int main(void){
int * comm;
pid_t pid;
/* map to allow child processes access same array */
comm = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*comm = 0;
pid=fork();
if(pid == 0){ /* child process */
signal(SIGUSR1, sig_handler); /* catch signal */
do {
/* do things */
} while(a == 0);
printf("Child exit(0)\n");
*comm = 2;
exit(0); /* exit for child process */
} /* if(pid == 0) - code below is parent only */
printf("Started child process, sleeping %d seconds\n", MAX);
sleep(MAX);
printf("Send signal to child\n");
kill(pid, SIGUSR1); /* send SIGUSR1 */
while(*comm != 2) usleep(10000);
printf("Child process ended\n");
/* clean up */
munmap(comm, sizeof(int));
return 0;
}
系统
clang 在 termux (clang 9.0.1) 和 lubuntu (clang 6.0.0-lubuntu2) 上显示了这一点。
【问题讨论】:
-
我认为您需要使用
volatile sig_atomic_t而不是static int。 -
还要注意
printf不是signal safe function。 -
如果您的代码正确,优化不会改变结果,但可能会改变获得结果的速度。如果您的代码不正确,优化器可能会根据更改结果的未定义行为做出决定,但就编译器而言没有问题,因为对于未定义行为,任何结果都是有效的。我没有查看您的代码来发现未定义行为的位置,但如果优化改变了结果,则可能存在未定义行为的问题。
-
@M.M — 这不是我说的吗?
标签: c optimization clang fork