2017-03-13 36 views
0

有一天,我發現了關於並行線程互斥執行可能的錯誤一篇有趣的文章,隨後進行討論:pthreads互斥體實現中是否存在基本錯誤?

https://lwn.net/Articles/575460

我現在的並行線程庫(和一般的多線程編程)的知識是太可憐了我理解大部分的討論,但我必須承認這導致了一些令人不安的結論。這是否意味着當前pthreads mutex的實現確實存在嚴重缺陷,因此,Linux內核(無疑嚴重依賴於多線程代碼)可能會涌現出來源於該缺陷的嚴重錯誤?我一直認爲代碼是基本的,低級的和基本的,像基本的同步原語,比如互斥體已經過徹底的測試(甚至被證明是正確的)。相反,我們突然發現大家多年來沒有注意到的「特例」,包括Linus Torvalds在內的任何人都無法確定它在內核代碼中可能出現的頻率。 聽起來很恐怖,不是嗎?

無論如何,有什麼問題和它(本文是從2013年末)可能的解決方案的現狀如何?互斥體實施是否已更改爲涵蓋省略的特例?或者是否改變了庫文檔(POSIX標準?)以加強可以安全使用互斥體的條件?有沒有做過任何事情?學習pthreads庫是否有意義,如果它很可能是腐敗和不可靠的?或者,我對這個問題的理解是錯誤的,根本沒有問題?

+0

鏈接的討論與POSIX互斥體無關。 POSIX互斥體是*用戶空間*對象。討論的內容是在* kernel *空間中運行的* kernel *鎖。另外我懷疑基本錯誤不在內核鎖中,它的使用方式是 - 釋放鎖之後釋放內存,這意味着等待鎖的第二個線程將獲得鎖,遞增有問題的引用計數,然後嘗試使用已釋放的內存。 –

+0

@AndrewHenle Btw大多數互斥體(包括POSIX和C++ 11)明確允許該文章中描述的用法。 – Ivan

+0

@Ivan我不確定你的觀點是什麼。曾經發布的C,C++和POSIX標準的每個版本都無法防止出錯代碼。你讀過整篇文章了嗎?使用位於該內存中的鎖來保護任何內存幾乎是不可能的,無論該鎖是POSIX互斥鎖,Linux內核鎖還是C++ 11互斥鎖。這種內存在鎖定期間不能被釋放,並且有***無法阻止另一個線程等待獲取線程在釋放鎖定後釋放的鎖定。這是一個錯誤。 –

回答

0

P線程是POSIX線程和值得了解獨立任何特定的實現。 Linux不是唯一的。 Pthreads已經過嘗試和測試,即使在那裏也能很好地工作。

如果你讀了文章仔細問題只體現在某些情況下。只有在鎖座喚醒第三根線,並且等待鎖的時刻,您必須讓一根線等待獲取鎖。此外,其不安全的原因在於,「旋轉」線程的行爲會導致第三個線程出現問題,因爲它認爲可以安全地釋放包含互斥體的對象,當第三個線程將不會使用它時。

其實這個問題是不是互斥的實現在所有,而不是這麼多它是如何被使用的,但肯定的修復,使其安全地使用這種方式會受到歡迎。 這似乎是內核社區關心的問題,因爲這個問題可能表現在相當廣泛的編碼模式中(即參考計數來決定何時可以安全刪除)。 如果您有興趣,您可以檢查內核更改歷史記錄以查看是否有內存更改歷史記錄。

免責聲明:我只是在外圍熟悉這些問題。更熟悉互斥體實現和內核的人可能會更好地指導您。

0

對於POSIX和C++ 11互斥鎖,該文章中顯示的互斥鎖使用有效。 Glibc有類似的bug,現在已經修復。

我認爲每一個同步glibc中原始有類似的錯誤在一些點。這裏是一些(現在都固定):在並行線程障礙

  • Bug 12674

    • Bug 13065競爭條件 - sem_post/sem_wait比賽造成sem_post返回EINVAL

    我不知道什麼是它的狀態現在,但很可能至少共享的POSIX primites不完全符合。

    Musl libc試圖提供POSIX原語的正確實現。這就是爲什麼pthread_barrier_wait共享屏障共享全局進程內鎖與MAP_FIXEDmmap調用。而且我不確定這是否能解決所有問題。很高興知道glibc如何處理這個問題,很可能它不會,所以這可能是一個「基本錯誤」的例子。

    您可能想檢查musl作者的個人資料 - Rich Felker - 和他的問題列表在這裏找到許多問題。