web-dev-qa-db-ja.com

Pthreadミューテックスアサーションエラー

Linuxベースの(アーム)通信アプリケーションで予期しないときに次のエラーが発生します。

pthread_mutex_lock.c:82: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.

Googleはそのエラーへの多くの参照を表示しますが、私の状況に関連すると思われる情報はほとんどありません。誰かがこのエラーのトラブルシューティング方法についていくつかのアイデアを私に与えることができるかどうか疑問に思っていました。この主張の一般的な原因を誰かが知っていますか?

前もって感謝します。

35
Dave Causey

4日間連続して堅実にロックします。これで勝利を宣言します。答えは「愚かなユーザーエラー」です(上記のコメントを参照)。 mutexは、それをロックしたスレッドによってのみロック解除されます。私を支えてくれてありがとう。

27
Dave Causey

TLDR:破棄された/初期化されていないミューテックスをロックしていないことを確認してください。

OPには答えがありますが、他の誰かが私と同じ問題を抱えている場合に備えて、私の問題を共有したいと思いました。

アサーションはロック解除ではなく__pthread_mutex_lockにあることに注意してください。これは、私には、この問題を抱えている他のほとんどの人が、ミューテックスをロックしたスレッドとは別のスレッドでミューテックスをロック解除していないことを示唆しています。破壊されたミューテックスをロックしているだけです。

私にとっては、静的コールバック関数を他のクラスに登録するクラス(Fooと呼びましょう)がありました(Barと呼びましょう)。コールバックにはFooへの参照が渡されていて、Fooのメンバーであるミューテックスを時々ロック/ロック解除していました。

この問題は、Fooインスタンスがまだコールバックを使用しているときにBarインスタンスが破棄された後に発生しました。コールバックは存在しなくなったオブジェクトへの参照を渡されていたため、ガベージメモリで__pthread_mutex_lockを呼び出していました。

C++ 11のstd::mutexstd::lock_guard<std::mutex>を使用していたことに注意してください。ただし、Linuxを使用していたため、問題はまったく同じでした。

3
rationalcoder

私は同じ問題に直面し、グーグルはここに私を送りました。私のプログラムの問題は、状況によっては、ロックする前にミューテックスを初期化していなかったことでした。

受け入れられた回答のステートメントは正当ですが、この主張の失敗の原因ではないと思います。エラーはpthread_mutex_lock(およびnotロック解除)。

また、いつものように、エラーはコンパイラーではなくプログラマーのソースコードにある可能性が高くなります。

2
Shayan Pooya

私が頻繁に行ったグーグルの簡単なビットは、コンパイラの不適切な最適化に原因があることがよくあります。まともな合計は here です。アセンブリの出力を見て、gccが正しいコードを生成しているかどうかを確認することは価値があるかもしれません。

それか、またはpthreadライブラリが使用するメモリを踏みにじっているのです...この種の問題は見つけるのがかなり難しいです。

1
Chris Arguin

私はこの問題を乗り越えて他の人を助けるかもしれないと思ったところです。私の場合、問題はミューテックスをロックし、共有変数をチェックしてから戻るという非常に単純な方法で発生しました。このメソッドは、ワーカースレッドを作成する基本クラスのオーバーライドです。

このインスタンスの問題は、基本クラスがコンストラクターでスレッドを作成していたことでした。次にスレッドが実行を開始し、メソッドの派生クラスの実装が呼び出されました。残念ながら、派生クラスはまだ構築を完了しておらず、派生クラスのミューテックスはミューテックス所有者として初期化されていないデータを持っています。これにより、実際にはロックされていないときにロックされているように見えました。

解決策は本当に簡単です。 StartThread()と呼ばれる基本クラスに保護されたメソッドを追加します。これは、基本クラスからではなく、派生クラスコンストラクターで呼び出す必要があります。

0
ReefSmacker

私は同じ問題を抱えていました

私の場合、スレッド内でvertica dbをodbcに接続し、次の設定を/etc/odbcinst.iniに追加して問題を解決しました。これまでのところ例外は発生しません。

[ODBC]
Threading = 1

クレジット: hynek

0
ismail

/etc/odbcinst.iniファイルにThreading = 0を追加すると、この問題が修正されました

0