草庐IT

c++ - POSIX 计时器信号未在信号处理程序中被阻止

coder 2024-02-24 原文

我正在设置一个 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

最佳答案

不是设置周期性定时器,而是在信号处理程序结束时再次触发。

创建计时器时执行此操作

// start the timer
//struct itimerspec timerSpec;
this->timerSpec_.it_value = firstExecTime;
this->timerSpec_.it_interval = 0; //one-shot 
if( timer_settime(*timerIn, TIMER_ABSTIME, &this->timerSpec_, NULL) == -1 )
{
    return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't start timer for timer" );
}

// from now we will shoot the timer with this value
this->timerSpec_.it_value = ElmoSynchronizer::getTimespecFromDouble(1.0/rate_hz);

// store *timerIn in also in ElmoSynchronizer
this->timerId_ = *timerIn;

然后将此附加到 ElmoSynchronizer::rootPvtCallback 函数的末尾

//shoot our the timer again
if( timer_settime(elmoSync->timerId_, 0, &elmoSync->timerSpec_, NULL) == -1 )
{
    return CanStatus( CanStatus::SYSTEM_ERROR, __FUNCTION__, "Couldn't restart timer" );
}

顺便说一下,我会用线程和信号量来完成整个事情,这样同步器就可以简单地检查 PVT 更新过程是否在定义的持续时间内结束。 POSIX 提供了它们并且并不比计时器更难实现。

关于c++ - POSIX 计时器信号未在信号处理程序中被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4514011/

有关c++ - POSIX 计时器信号未在信号处理程序中被阻止的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  7. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  10. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

随机推荐