【Ubuntu 12.04 alpha 2】ファイルマネージャー(Nautilus)を起動するとnautilus-dropboxが原因でコアダンプで落ちる。-- glibが2.31.18になったのが原因みたい(修正済みです) [ubuntu]
--- 2012/2/24 追記 ---
もう修正版の2.31.18-0ubuntu2が出ています。
やはりオーバーフローが問題でした。それに、バグ報告は下記メインのものでした。
https://bugs.launchpad.net/ubuntu/+source/nautilus-dropbox/+bug/932627
修正の考え方は基本的に同じですが、実際のコードは明らかに私の方が下手です。キャストすればいいのは分かてたのですが、どこでキャストすればいいかよく分からなかったので、一番安全策でコーディングしました。
ただ、不思議なのは、g_async_queue_timed_popは直しておいて、次に記述してある関数g_async_queue_timed_pop_unlockedも同じ問題があるに直していません。
なぜ?? 使わないからかな??
--- 2012/2/24 追記終わり ---
先日(2012/2/21前後)から、ファイルマネージャー(Nautilus)を起動するとnautilus-dropboxが原因で落ちるようになってしまいました。
結構、Dropboxの中にデータを入れているので困ってしまいました。
Launchpad にも報告されていて、下記です。
https://bugs.launchpad.net/ubuntu/+source/nautilus/+bug/932556
pthread_cond_timedwaitという関数が入力パラメータがおかしいというエラーです。
それで、 pthread_cond_timedwaitという関数はnautilus-dropboxからどのように呼ばれているかというと、
nautilus_dropbox_get_file_items ( nautilus-dropbox.c: nautilus-dropbox)
↓
g_async_queue_timed_pop ( gasyncqueue.c :glib)
↓
g_async_queue_pop_intern_unlocked ( gasyncqueue.c :glib)
↓
g_cond_wait_until ( gthread-posix.c :glib)
↓
pthread_cond_timedwait
と呼ばれていきます。
それで、glibを経由して呼ばれているのですがglib2.0 2.1.18( https://launchpad.net/ubuntu/+source/glib2.0/2.31.18-0ubuntu1)の下記のdiffを見ると、
http://launchpadlibrarian.net/93542878/glib2.0_2.31.16-0ubuntu2_2.31.18-0ubuntu1.diff.gz
上記リンクの内容を見ると、g_async_queue_pop_intern_unlocked関数に修正が入っています。
修正内容というのが、g_cond_timed_wait関数を呼んでいたのを止めて、g_cond_waitまたはg_cond_wait_untilを呼ぶようにした事。それと、引数のend_timeの型がGTimeVal * から gint64になったことです。
問題はGTimeValの中身は2つの要素があってそれぞれglong型。ところが、 g_async_queue_pop_intern_unlockedの引数であるend_timeはgint64型です。
そこで、g_async_queue_timed_pop関数は下記のようなコードです。(ver. 2.31.18時点)
gpointer
g_async_queue_timed_pop (GAsyncQueue *queue,
GTimeVal *end_time)
{
gint64 m_end_time;
gpointer retval;
g_return_val_if_fail (queue, NULL);
if (end_time != NULL)
{
m_end_time = g_get_monotonic_time () +
(end_time->tv_sec * G_USEC_PER_SEC + end_time->tv_usec -
g_get_real_time ());
}
else
m_end_time = -1;
g_mutex_lock (&queue->mutex);
retval = g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
g_mutex_unlock (&queue->mutex);
return retval;
}
上記の赤字の所はglong型(end_time->tv_secやend_time->tv_usec)に入っているデータを計算してgint64型(m_end_time)に入れていますが、私の使っているのは32bit版なので、glongは4バイトgint64は8バイトになります。
私の記憶が正しければ、 end_time->tv_sec * G_USEC_PER_SECの計算やその結果を一旦格納する型はglong型(32bitレジスターが1つ分のサイズ)なはず・・・運が悪いとオーバーフローしてしまいます。
というわけで、下記のように書き直して見ました。
gpointer
g_async_queue_timed_pop_unlocked (GAsyncQueue *queue,
GTimeVal *end_time)
{
gint64 m_end_time,tmp_end_time;
g_return_val_if_fail (queue, NULL);
if (end_time != NULL)
{
m_end_time = g_get_monotonic_time ();
tmp_end_time = end_time->tv_sec;
tmp_end_time *= G_USEC_PER_SEC;
m_end_time += tmp_end_time;
m_end_time += end_time->tv_usec;
m_end_time -= g_get_real_time ();
}
else
m_end_time = -1;
return g_async_queue_pop_intern_unlocked (queue, TRUE, m_end_time);
}
※記述がスマートでなくてすみません。
要するに、一回gint64型の変数に代入してから全て計算しているだけです。
g_async_queue_timed_pop_unlocked関数も同じようになっていたので、同じように修正しました。
あとはビルドして入れたら、下記のように動きました。
上図のdpkg- l libglib2.0-0の出力結果は、リポジトリのものそのままの値になっていますが、実際には本記事に記述したように私が修正したものです。
それと、私の修正が正しければ32bit版を使用している人のみ発生するはずで、64bit版の方は大丈夫なはずです。(glongの型の大きさとgint64の型の大きさが一緒だから)
早く直してね。。(*・人・*) オ・ネ・ガ・イ♪
←耐水ノート
この前テレビでこれ見ました。
この製品かはわかりませんが・・・
水の中でも鉛筆でかける。
私はヨットに乗るので、こういうのはいいかも・・・
コメント 0