修改系統時間導致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按相對時間等待超時完整示例代碼”
https://blog.csdn.net/yichigo/article/details/23459613

按照文章的實現,完美解決了該問題

@@ -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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章