修改系统时间导致pthread_cond_timedwait超时问题的解决

最近在调查一个相机在使用过程中相机莫名奇妙报申请预览超时的问题,
报的错误如下:

camxsession.cpp:1269 ProcessCaptureRequest() Lets do a Reset 
camxchi.cpp:588 ChiSubmitPipelineRequest() Submit request failed with error 9.

本来以为是CPU使用过高,导致预览上报超时,然后各种分析性能功耗。进入了一个更大的坑,无法自拔!!!
最近找到了复现规律,只要修改下系统时间,都会报上述错误!!!天坑啊!!!

于是仔细研究了下camx的代码,在不经意间,把锁的源码打开看看了,发现了这个天坑的原因(天啊,谁会想到,锁的实现竟然存在问题!!)
代码如下:

CamxResult Condition::TimedWait(
    OSMutexHandle*  phMutex,
    UINT            timeoutMilliseconds)
{
    
    

    CamxResult      result              = CamxResultSuccess;
    INT             waitResult          = 0;
    UINT            timeoutSeconds      = (timeoutMilliseconds / 1000UL);
    UINT            timeoutNanoseconds  = (timeoutMilliseconds % 1000UL) * 1000000UL;
    struct timespec timeout             = {
    
    0};

    // Calculate the timeout time
    //通过CLOCK_REALTIME获取的时间是受系统时间影响的!!!
    clock_gettime(CLOCK_REALTIME, &timeout);
    timeoutSeconds      += (static_cast<UINT>(timeout.tv_nsec) + timeoutNanoseconds) / 1000000000UL;
    timeoutNanoseconds  =  (static_cast<UINT>(timeout.tv_nsec) + timeoutNanoseconds) % 1000000000UL;
    timeout.tv_sec      += static_cast<INT>(timeoutSeconds);
    timeout.tv_nsec     =  static_cast<INT>(timeoutNanoseconds);

    //如果在pthread_cond_timedwait的过程中,系统时间突然变大,这个锁直接返回CamxResultETimeout
    waitResult = pthread_cond_timedwait(&m_conditionVar, phMutex, &timeout);

    if (waitResult != 0)
    {
    
    
        // Check errno for reason for failure
        if (ETIMEDOUT == waitResult)
        {
    
    
            result = CamxResultETimeout;
        }
        else
        {
    
    
            result = CamxResultEFailed;
        }
    }

    return result;
}

百度了下,说是将CLOCK_REALTIME改为CLOCK_MONOTONIC再获取的时间就可以不受系统时间影响。
修改后,发现还是不生效,本来是偶现的问题,成了必现问题!!!!

今天在万能的CSDN中,阅读了一篇大牛文章:
pthread_cond_timedwait按相对时间等待超时完整示例代码

按照文章的实现,完美解决了该问题

@@ -1741,7 +1741,9 @@ CamxResult Condition::Initialize(
 
     m_pResource = pResource;
 
-    if (pthread_cond_init(&m_conditionVar, NULL) == 0)
+    pthread_condattr_setclock(&m_cattr, CLOCK_MONOTONIC);
+
+    if (pthread_cond_init(&m_conditionVar, &m_cattr) == 0)
     {
    
    
         m_validConditionVar = TRUE;
     }
@@ -1795,7 +1797,7 @@ CamxResult Condition::TimedWait(
     struct timespec timeout             = {
    
    0};
 
     // Calculate the timeout time
-    clock_gettime(CLOCK_REALTIME, &timeout);
+    clock_gettime(CLOCK_MONOTONIC, &timeout);

猜你喜欢

转载自blog.csdn.net/u010116586/article/details/94748075
今日推荐