OpenRTMFP/Cumulus Primer(19)獨立使用CumulusLib時的執行緒安全Bug

鍾超發表於2012-06-07

OpenRTMFP/Cumulus Primer(19)獨立使用CumulusLib時的執行緒安全Bug

  • 作者:柳大·Poechant(鍾超)
  • 郵箱:zhongchao.ustc#gmail.com(# -> @)
  • 部落格:Blog.CSDN.net/Poechant
  • 日期:June 7nd, 2012

OpenRTMFP/Cumulus 提供了 CumulusLib 可以供其他 RTMFP 應用使用,而不侷限於 CumulusServer。

一般來說,Thread A 會準備好要 push 的訊息,然後 Thread A 向訊息佇列 push 訊息。

但是 CumulusLib 中實現的,是 Thread A 向訊息佇列 push 訊息,然後根據這個訊息在佇列中的指標,再向訊息內填寫欄位。並期望如下:

Resize icon

由於在 CumulusServer 中,一個 Client 只在一個執行緒內被操作,相應的 FlowWriter 也不會出現跨執行緒的問題。但是如果單獨使用 CumulusLib,如果出現執行緒通訊,並且共享 FlowWriter 的話,就會共享訊息佇列,此時可能出現這種情況。

Resize icon

這就導致了很嚴重的錯誤,會使得程式崩潰。修正的方式,可以是將訊息完全準備好之後,再放入佇列,如下:

/*
 * author:  michael
 * date:    June 6th, 2012
 * type:    add
 */
MessageBuffered* FlowWriter::createAMFMessage(const std::string& name)

    // signature.empty() means that we are on the flowWriter of FlowNull
    if (!(_closed || signature.empty() || _band.failed())) {
        MessageBuffered* pMessage = new MessageBuffered();
        MessageBuffered& message(*pMessage);
        writeResponseHeader(message.rawWriter,name,0);
        return pMessage;
    }

    MessageBuffered& message(_MessageNull);
    writeResponseHeader(message.rawWriter,name,0);
    return NULL;
}

然後再呼叫時最後再增加 push 操作:

/*
 * author:  michael
 * date:    June 6th, 2012
 * type:    add
 */
void FlowWriter::pushAMFMessage(MessageBuffered* pMessage) {
    if (pMessage != NULL) {
        _messages.push_back(pMessage);
    }
}

這樣就使得訊息的資料被寫完了,才被放入佇列中,如下:

Resize icon

不過如果考慮執行緒安全,多個執行緒對同一個訊息佇列進行操作時,就要加鎖:

/*
 * author:  michael
 * date:    June 6th, 2012
 * type:    add
 */
void FlowWriter::pushAMFMessage(MessageBuffered* pMessage) {
    if (pMessage != NULL) {
        Poco::Mutex::ScopedLock lock(msgQueueMutex);
        _messages.push_back(pMessage);
    }
}

這樣就基本解決了這個執行緒安全問題。

另外,使用 CumulusLib 要遵循 GPL 協議,一定不要忘記。

-

轉載請註明來自柳大·Poechant(鍾超)的CSDN部落格:Blog.CSDN.net/Poechant

-

相關文章