2014-04-03 73 views
2

我正在開發一個使用3個模塊提供打印,捕獲和觸發功能的照片展位應用程序。這個想法是人們可以爲它開發擴展這個功能的模塊。這些模塊被實現爲共享庫,當用戶點擊「開始」時,這些共享庫在運行時加載。在運行時加載的共享庫中的Libcurl和curl_global_init

我想實現一個「打印」到Facebook圖片庫的打印機模塊。我想爲此使用libcurl。我的問題是初始化函數:curl_global_init() libcurl API文檔指出,此函數絕對不是線程安全的。從the docs

此函數不是線程安全的。當程序中的任何其他線程(即共享相同內存的線程)正在運行時,您不得調用它。這並不意味着沒有其他使用libcurl的線程。由於curl_global_init()調用類似線程不安全的其他庫的函數,因此它可能會與使用這些其他庫的其他線程發生衝突。

Elsewhere的文檔中,它說:

當你正在編寫使用libcurl的代碼不是主程序,而是一個模塊化一塊程序的全局常量局勢值得特別考慮,例如另一個庫。作爲一個模塊,你的代碼不知道程序的其他部分 - 它不知道他們是否使用libcurl。它的代碼不一定會在整個程序的開始和結束時運行。

像這樣的模塊必須具有自己的全局常量函數,就像curl_global_init()和curl_global_cleanup()一樣。模塊因此在程序的開始和結束時都有控制權,並且有一個地方可以調用libcurl函數。

......這似乎解決了這個問題。但是,這似乎意味着我的模塊的init()finalize()函數將在程序的開始和結束處被調用。由於模塊設計爲在運行時可以交換,所以我無法做到這一點。就算我想到了,我的應用程序使用的GLib,這佔其documentation,這是從來沒有安全的假設沒有運行的線程:

...從版本2.32,GLib的線程系統會自動在啓動初始化的程序,並且所有線程創建函數和同步原語都可以立即使用。

請注意,即使您自己不調用g_thread_new(),也不安全地假定程序沒有線程。 GLib和GIO可以並且將爲他們自己的目的創建線程...

我的問題是:有什麼方法可以在我的應用程序中安全地調用curl_global_init()?我可以將電話curl_global_init()curl_global_cleanup()放在我的模塊的init()finalize()功能中嗎?我是否需要找到另一個HTTP庫?

回答

3

首先,您不會真的發現沒有這些限制的任何其他庫,因爲它們由具有這些限制的第三方(主要是SSL)的libcurl繼承。例如OpenSSL。

這就是說,global_init的線程安全情況是非常不幸的,我們(在curl項目中)真的很不喜歡它,但是隻要我們使用這些其他庫,我們也不能做太多的事情。這也意味着您的情況完全取決於您的libcurl構建使用的依賴庫。

在大多數情況下,您會根據您的建議,從您的模塊init()函數中調用curl_global_init()以完全正常。我不能保證這是安全的,當然有100%的確定性,因爲這裏有一些我不能說的未知數。

+0

感謝您的回覆。我一直在考慮從我的模塊中派生一個流程,並讓其子流程出於其他原因處理實際工作,但是我決定採取一種更簡單的解決方案。但是,在我看來,這可能是解決此問題最安全的方法。 – Chris

+0

@Chris請注意,如果您在多線程程序中使用fork(),則在成功執行execve()之前,不得調用任何異步信號不安全的函數(即,幾乎任何內容)。您需要創建一個單獨的exectuable。 – Demi