【发布时间】:2016-06-16 16:45:18
【问题描述】:
有人可以解释为什么 SIGSEGV 在 5-7 次迭代后计时器会失败?
这两种情况都会发生:同步和不同步。 操作系统为 Ubuntu 15.04,Ubuntu GLIBC 2.21-0ubuntu4。
void timer_thread (sigval signal_value) {
printf ("Timer callback!\n");
}
int main(int argc, char* argv[]) {
const int TIMER_COUNT = 300;
for (int i = 0; i < 10000; i++) {
int status = 0;
timer_t timer_id[TIMER_COUNT] = {};
memset(&timer_id[0], 0, sizeof(timer_t)*TIMER_COUNT);
for (int j = 0; j < TIMER_COUNT; j++) {
struct itimerspec ts = {};
struct sigevent se = {};
memset(&ts, 0, sizeof(itimerspec));
memset(&se, 0, sizeof(sigevent));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_int = j;
se.sigev_notify_function = timer_thread;
// Specify a repeating timer that fires each 100000 nanosec.
memset(&ts, 0, sizeof(ts));
ts.it_value.tv_nsec = 100000;
ts.it_interval.tv_nsec = 100000;
status = timer_create(CLOCK_REALTIME, &se, &timer_id[j]);
assert(!status && "Create timer");
status = timer_settime(timer_id[j], 0, &ts, 0);
assert(!status && "Set timer");
}
for (int j = 0; j < TIMER_COUNT; j++) {
usleep(100);
//stop and delete
status = timer_delete(timer_id[j]);
assert(!status && "Fail delete timer");
}
}
printf("Success!\n");
return 0;
}
GDB 回溯:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 __pthread_create_2_1 (newthread=newthread@entry=0x7f00e9817e28, attr=attr@entry=0x11c47e8, start_routine=start_routine@entry=0x7f00e93f6eb0 <timer_sigev_thread>, arg=<optimized out>)
at pthread_create.c:711
711 pthread_create.c: No such file or directory.
(gdb) bt
#0 __pthread_create_2_1 (newthread=newthread@entry=0x7f00e9817e28, attr=attr@entry=0x11c47e8, start_routine=start_routine@entry=0x7f00e93f6eb0 <timer_sigev_thread>, arg=<optimized out>)
at pthread_create.c:711
#1 0x00007f00e93f6e7a in timer_helper_thread (arg=<optimized out>) at ../sysdeps/unix/sysv/linux/timer_routines.c:125
#2 0x00007f00e91db6aa in start_thread (arg=0x7f00e9818740) at pthread_create.c:333
#3 0x00007f00e866feed in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
构建命令行:/usr/bin/c++ -lrt -lpthread -g ./main.cc
【问题讨论】:
-
请确认您在不断地创建、超时然后删除 300 个计时器。一遍又一遍,一遍又一遍。
-
对。我创建了大约 300 个计时器,然后是睡眠或等待条件变量,并且在所有计时器多次调用之后,删除所有计时器。大约 5 次是工作,然后在 6 日或以后它会失败。
-
而且不需要 300 个计时器,它会在 50 个或更少的计时器时失败。
-
这似乎是一个运行时问题,但发布的代码缺少#include 语句。您希望我们猜测包含哪些头文件吗?
-
我不会重现这个问题。我在 VM 中运行 Mint 17.2 x86_64 内核 v3.16.0(我猜这会使问题变得更糟)。尝试在另一个终端窗口中运行它以查看您获得的“信号队列限制”值:
cat /proc/[programs-PID]/status | grep SigQ。我得到如下结果:SigQ: 271/22308。第一个值是排队的信号数,第二个是最大值。这里的第一个永远不会超过 300(正如您所期望的,因为一次最多有 300 个计时器处于活动状态)。看看您是否在第一个条目中获得更高的值或在第二个条目中获得非常低的值。
标签: c timer posix glibc ubuntu-15.04