2017-02-22 79 views
1

我正在測試我使用libuv開發的簡單服務器體系結構。 每當服務器從客戶端收到一些東西時,它就會按'\ r'分割主體並向所有觀察者廣播每條消息。多個同時調用uv_write有時不起作用

然後,我用來測試的觀察者使用相同的原始消息(回顯服務器)調用server-> write()方法。

問題是,每次運行程序時,它都會隨機地運行或不運行。

當它不工作,該錯誤信息是:

Assertion failed: (req->write_index < req->nbufs), function uv__write, file src/unix/stream.c, line 869. Abort trap: 6

全部代碼是在這裏:https://github.com/ghostec/film

大部分代碼是在這個文件中:https://github.com/ghostec/film/blob/master/server/server.cpp

編輯:顯然這與uv_queue_work內部調用uv_write的事實有關。由於它們都寫入相同的處理程序,因此如果在libuv循環內調用它們時出現故障,則會發生不良情況。不過,我不確定我的評估是否正確。

回答

1

正如documentationuv_write的提到:

注意:內存指向的緩衝區,直到回調函數被調用必須保持有效。這也適用於uv_write2()。

在另一邊,這是你的代碼:

void Server::write(Message message) { 
    uv_write_t req; 
    uv_buf_t* buf = new uv_buf_t(); 
    buf->base = &(std::vector<char>(message.data.begin(), message.data.end()))[0]; 
    buf->len = message.data.size(); 
    uv_write(&req, message.handle, buf, 1, [](uv_write_t* req, int status) -> void {}); 
    delete buf; 
} 

特別是,該行的代碼味道:

buf->base = &(std::vector<char>(message.data.begin(), message.data.end()))[0]; 

還要注意的是,同樣適用於uv_buf,因此在回調被稱爲嗅覺之前刪除它。除了懷疑libuv在內部失敗之外,我想說你應該對它的執行情況非常感激,即使你不忠於庫的需求,在每次使用uv_write時都不會看到問題。


對於您所標記的問題與c++,我建議你使用one of the existing wrappers是正確地管理內存和數據結構爲你的引擎蓋下。請參閱上述鏈接中的綁定部分。

+0

我懷疑循環工作的[刪除請求](https://github.com/ghostec/film/blob/master/server/server.cpp#L49)並不是一個好主意。 ;-) – skypjack

+0

非常感謝!解決了你指出的錯誤之後,我仍然有同樣的問題。 新功能:https://github.com/ghostec/film/blob/master/server/server.cpp#L36 如果我不在這裏使用uv_queue_work https://github.com/ghostec/film/ blob/master/server/server.cpp#L55,只是用觀察者(消息)替換整個內部的隨機崩潰停止。 –

+0

我建議你從答案中鏈接的項目中獲得靈感。我無法一遍又一遍地查看代碼來解決任何問題,我現在正在工作,對不起。 – skypjack