I am setting up a POSIX timer to call a function at a given speed. I set up a signal handler and initialize a timer, etc ... everything works. However, according to all the documentation I read, I should never receive a signal from a timer while I am in a signal handler (it should be automatically blocked). To take this a step further, I even set sa_mask sigaction to block all signals ... I still get some calls to the signal handler ...
Handler settings:
// 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" ); }
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