今日のGUIクラッシュ(マルチスレッド関連)

threadを使うwxPythonによるGUIがクラッシュするときに表示される、エラーメッセージのいくつかのパターン。

  • パターン1

(python:14799): Gtk-CRITICAL **: gtk_text_layout_wrap_loop_start: assertion `layout->one_style_cache == NULL' failed

  • パターン2

(python:15403): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion `layout->wrap_loop_count == 0' failed

glibc detected *** python: double free or corruption (fasttop): 0x0a68b9b8 ***
  • パターン3

Gtk-ERROR **: file gtktextlayout.c: line 1990 (gtk_text_layout_get_line_display): should not be reached
aborting...

glibc detected *** python: corrupted double-linked list: 0x091f6bf8 ***
  • パターン4

(a.out:16337): Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
will invalidate all outstanding iterators

ここら辺が解決方法か。↓
python - multithreading issue with wx.TextCtrl (or underlying GTK+) - Stack Overflow

要約すると、これらのエラーを避けるため、wxPythonにおいてマルチスレッドのアプリケーションを作成する際の注意点は、以下のようにまとめられる*1

  • GUI上の操作(自分の場合であれば、別スレッドで実行した結果をGUI画面上に表示したりということか)は、メインスレッドで行わなければならない。
  • その訳は、多くのUnix GUIライブラリはスレッドセーフ(thread-safe)でないことが往々にしてあるから。
  • wx.Bitmapで画面に何か表示したりするときも危ない。
  • バックグランドスレッドから、UIスレッドに何かメッセージを送って、画面表示を更新する場合等には、wx.CallAfter()を使うと良い。

つまり、絵にするとこんな感じの処理方法で実装すべき、ということになる。↓

一方、今まではこんな感じでやっていたので頻繁にクラッシュした。↓

*1:wxPython in Action」18.6節