POSIX 定时器信号在信号处理程序中未被阻止
我正在设置一个 POSIX 计时器以给定的速率调用函数。我设置了一个信号处理程序并初始化计时器等......一切正常。但是,根据我读过的所有文档,当我在信号处理程序中时,我永远不应该收到来自计时器的信号(它应该自动被阻止)。为了更进一步,我什至设置了 sigaction 的 sa_mask 来阻止所有信号...我仍然多次调用信号处理程序...
设置处理程序:
// establish the signal handler
sigset_t blockMask;
struct sigaction sigact;
sigfillset(&blockMask);
//sigemptyset(&blockMask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = callbackIn;
sigact.sa_mask = blockMask;
if( sigaction(ElmoSynchronizer::NEXT_RT_SIGNAL_NUMBER, &sigact, NULL) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't establish signal handler for timer" );
}
// create the timer
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = ElmoSynchronizer::NEXT_RT_SIGNAL_NUMBER;
sev.sigev_value.sival_ptr = this;
if( timer_create(CLOCK_REALTIME, &sev, timerIn) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't create POSIX timer for timer" );
}
// start the timer
struct itimerspec timerSpec;
timerSpec.it_value = firstExecTime;
timerSpec.it_interval = ElmoSynchronizer::getTimespecFromDouble(1.0/rate_hz);
if( timer_settime(*timerIn, TIMER_ABSTIME, &timerSpec, NULL) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't start timer for timer" );
}
回调(是的,我知道 printfs 在信号处理程序):
void ElmoSynchronizer::rootPvtCallback(int sig, siginfo_t *si, void *uc)
{
// get a pointer to the ElmoSynchronizer calling this
ElmoSynchronizer *elmoSync = (ElmoSynchronizer*)si->si_value.sival_ptr;
struct timespec startTime;
clock_gettime(CLOCK_REALTIME, &startTime);
uint32_t expectedTime_us = elmoSync->getMasterClockTimeFromTimespec_us(elmoSync->m_pvtSupplyStartTime) + ((elmoSync->m_updateIteration * elmoSync->m_elmoUpdatePeriod_ms) * 1000);
uint32_t actualTime_us = elmoSync->getMasterClockTimeFromTimespec_us(startTime);
uint32_t currIter = elmoSync->m_updateIteration+1;
printf("---> PVT update - iteration %u @ %u\n", currIter, elmoSync->getMasterClockTimeFromTimespec_us(startTime));
fflush(stdout);
// iterate through all of our callbacks and call them!
for( unsigned int i = 0; i < elmoSync->m_elmos.size(); i++ )
{
// get the position/velocity pair
posVelPair_t pv = elmoSync->m_elmos[i].callback(elmoSync->m_elmos[i].elmo);
// now add the point to the elmo
elmoSync->m_elmos[i].elmo->addPvtPoints( pv.position_cnts, pv.velocity_cps, elmoSync->m_elmoUpdatePeriod_ms );
}
elmoSync->m_updateIteration++;
if( elmoSync->m_updateIteration == 250 )
{
usleep(elmoSync->m_elmoUpdatePeriod_ms*4000);
}
// make sure we executed fast enough
struct timespec endTime;
clock_gettime(CLOCK_REALTIME, &endTime);
double totalCallbackTime_s = getSecondsFromTimespec(ElmoSynchronizer::ts_subtract(endTime, startTime));
if( totalCallbackTime_s > (elmoSync->m_elmoUpdatePeriod_ms * 1.0E-3) )
{
//ROS_WARN("PVT update - Callback execution took longer than update period! %lfs actual / %lfs period", totalCallbackTime_s, (elmoSync->m_elmoUpdatePeriod_ms * 1.0E-3));
//overflowedRootPvtCallbackPeriod = true;
}
printf("<--- PVT update - iteration %u @ %u\n", currIter, elmoSync->getMasterClockTimeFromTimespec_us(endTime));
fflush(stdout);
/*
printf("PVT update - iteration: %u actual: %u expected: %u diff: %u cbTime: %u\n",
elmoSync->m_updateIteration, actualTime_us, expectedTime_us, actualTime_us-expectedTime_us, (uint32_t)(totalCallbackTime_s * 1.0E6));
fflush(stdout);
*/
}
输出:
---> PVT update - iteration 248 @ 13315103
<--- PVT update - iteration 248 @ 13315219
---> PVT update - iteration 249 @ 13346107
<--- PVT update - iteration 249 @ 13346199
---> PVT update - iteration 250 @ 13377104 // two entrances
---> PVT update - iteration 251 @ 13408109 // second entrance
<--- PVT update - iteration 251 @ 13408197
---> PVT update - iteration 252 @ 13439109
<--- PVT update - iteration 252 @ 13439254
---> PVT update - iteration 253 @ 13470120
<--- PVT update - iteration 253 @ 13470216
---> PVT update - iteration 254 @ 13501122
<--- PVT update - iteration 254 @ 13501213
<--- PVT update - iteration 250 @ 13501317 // exit for iteration 250
---> PVT update - iteration 255 @ 13532078
<--- PVT update - iteration 255 @ 13532170
---> PVT update - iteration 256 @ 13563109
<--- PVT update - iteration 256 @ 13563242
I am setting up a POSIX timer to call a function at a given rate. I setup a signal handler and initialize the timer, etc...everything works. However, according to all of the documentation I've read I should never receive a signal from the timer while I'm in the signal handler (it should automatically be blocked). To take this one step further, I even set the sa_mask of the sigaction to block all signals...I still get multiple calls to the signal handler...
Setting up the handler:
// establish the signal handler
sigset_t blockMask;
struct sigaction sigact;
sigfillset(&blockMask);
//sigemptyset(&blockMask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = callbackIn;
sigact.sa_mask = blockMask;
if( sigaction(ElmoSynchronizer::NEXT_RT_SIGNAL_NUMBER, &sigact, NULL) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't establish signal handler for timer" );
}
// create the timer
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = ElmoSynchronizer::NEXT_RT_SIGNAL_NUMBER;
sev.sigev_value.sival_ptr = this;
if( timer_create(CLOCK_REALTIME, &sev, timerIn) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't create POSIX timer for timer" );
}
// start the timer
struct itimerspec timerSpec;
timerSpec.it_value = firstExecTime;
timerSpec.it_interval = ElmoSynchronizer::getTimespecFromDouble(1.0/rate_hz);
if( timer_settime(*timerIn, TIMER_ABSTIME, &timerSpec, NULL) == -1 )
{
return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't start timer for timer" );
}
The callback (yes, i know printfs are bad in signal handlers):
void ElmoSynchronizer::rootPvtCallback(int sig, siginfo_t *si, void *uc)
{
// get a pointer to the ElmoSynchronizer calling this
ElmoSynchronizer *elmoSync = (ElmoSynchronizer*)si->si_value.sival_ptr;
struct timespec startTime;
clock_gettime(CLOCK_REALTIME, &startTime);
uint32_t expectedTime_us = elmoSync->getMasterClockTimeFromTimespec_us(elmoSync->m_pvtSupplyStartTime) + ((elmoSync->m_updateIteration * elmoSync->m_elmoUpdatePeriod_ms) * 1000);
uint32_t actualTime_us = elmoSync->getMasterClockTimeFromTimespec_us(startTime);
uint32_t currIter = elmoSync->m_updateIteration+1;
printf("---> PVT update - iteration %u @ %u\n", currIter, elmoSync->getMasterClockTimeFromTimespec_us(startTime));
fflush(stdout);
// iterate through all of our callbacks and call them!
for( unsigned int i = 0; i < elmoSync->m_elmos.size(); i++ )
{
// get the position/velocity pair
posVelPair_t pv = elmoSync->m_elmos[i].callback(elmoSync->m_elmos[i].elmo);
// now add the point to the elmo
elmoSync->m_elmos[i].elmo->addPvtPoints( pv.position_cnts, pv.velocity_cps, elmoSync->m_elmoUpdatePeriod_ms );
}
elmoSync->m_updateIteration++;
if( elmoSync->m_updateIteration == 250 )
{
usleep(elmoSync->m_elmoUpdatePeriod_ms*4000);
}
// make sure we executed fast enough
struct timespec endTime;
clock_gettime(CLOCK_REALTIME, &endTime);
double totalCallbackTime_s = getSecondsFromTimespec(ElmoSynchronizer::ts_subtract(endTime, startTime));
if( totalCallbackTime_s > (elmoSync->m_elmoUpdatePeriod_ms * 1.0E-3) )
{
//ROS_WARN("PVT update - Callback execution took longer than update period! %lfs actual / %lfs period", totalCallbackTime_s, (elmoSync->m_elmoUpdatePeriod_ms * 1.0E-3));
//overflowedRootPvtCallbackPeriod = true;
}
printf("<--- PVT update - iteration %u @ %u\n", currIter, elmoSync->getMasterClockTimeFromTimespec_us(endTime));
fflush(stdout);
/*
printf("PVT update - iteration: %u actual: %u expected: %u diff: %u cbTime: %u\n",
elmoSync->m_updateIteration, actualTime_us, expectedTime_us, actualTime_us-expectedTime_us, (uint32_t)(totalCallbackTime_s * 1.0E6));
fflush(stdout);
*/
}
Output:
---> PVT update - iteration 248 @ 13315103
<--- PVT update - iteration 248 @ 13315219
---> PVT update - iteration 249 @ 13346107
<--- PVT update - iteration 249 @ 13346199
---> PVT update - iteration 250 @ 13377104 // two entrances
---> PVT update - iteration 251 @ 13408109 // second entrance
<--- PVT update - iteration 251 @ 13408197
---> PVT update - iteration 252 @ 13439109
<--- PVT update - iteration 252 @ 13439254
---> PVT update - iteration 253 @ 13470120
<--- PVT update - iteration 253 @ 13470216
---> PVT update - iteration 254 @ 13501122
<--- PVT update - iteration 254 @ 13501213
<--- PVT update - iteration 250 @ 13501317 // exit for iteration 250
---> PVT update - iteration 255 @ 13532078
<--- PVT update - iteration 255 @ 13532170
---> PVT update - iteration 256 @ 13563109
<--- PVT update - iteration 256 @ 13563242
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要设置周期性计时器,而是在信号处理程序结束时再次触发它。
当您创建计时器时,执行此操作
将其附加到
ElmoSynchronizer::rootPvtCallback
函数的最后然后 PVT 更新过程是否在定义的持续时间内结束。
POSIX 提供了它们并且并不比定时器更难实现。
Instead of setting a periodic timer, shoot it again when the signal handler ends.
When you create the timer do this
Then append to the very end of the
ElmoSynchronizer::rootPvtCallback
function thisBy the way, I would make the whole thing with threads and semaphores, so the synchronizer could simply check whether the PVT updating process ended or not in a defined duration.
POSIX offers them and is not harder to implement than a timer.
当我需要调试信号处理程序时,我创建一个数组来放入调试信息(而不是使用 printf)。收集多个信号处理程序调用的数据,然后转储数组的内容以查看发生了什么。
您可能会看到不同的输出顺序。
When I need to debug signal handlers I make an array to put the debug info into (instead of using printf). Collect up data for a number of signal handler calls, then dump out the contents of the array to see what happened.
You might see a different order to the output.