#もともとDVDオーディオを聞きたくて購入>ヤマハ5.1chアンプ
##高騰している
#アナログ5.1ch入力つきのアンプってヤマハぐらいしかないんだよね.
#(むちゃくちゃ高いのならあるかも)
#on memory の ring buffer に debug print するという手もありますね。止まった時点、あるいはあるイベントを契機にlogを止めて調べる。例えば、netbsdのuvmhist (vm subsystem 用のlog機構).
#なるほど。そういうのをひとつ作っておくと便利かも>on memoryのring buffer
#そうえばdmesgもリングになってるよね、確か
#リングバッファって便利なんだけど、どばっとログが吐かれるような状況になると、最初の方が消えてしまって困ることがあって、サイズに悩むんですよね
#重要度とオーバヘッドのトレードオフですね。
#リングバッファじゃないけど、multilogでログを書いてKahuaを運用していて、何かで落ちる→daemontoolsが再起動→kahua UNIXドメインソケットが残ってて起動に失敗→daemontoolsが起動→(以下無限ループ)となって
#肝心の、最初に落ちた時のエラーログがexpireして消されてしまって悲しかったことがある
#kernel msgbufもリングですね。でもなぜかbsd系のdmesgには-c optionがない
#-c って何ですか?
#msg bufferのクリア
#使ったことなかった
#uvmhistは複数作れるから、粒度を変えて、とかもできるけど、でも実際にデバッグするときには、try & error の果てしない繰り返しになるから…
#ちなみに、実際に記録しているのはfmt stringと引数五つか六つなので、static でない object の中まではあとからはしらべられない。>uvmhist
#でもgcあれば…
#questionnaireがあるのか...
#enqueteってずっと使ってたけど、今後はこっちを使った方がいいのかなぁ
#ちょっと文字数が多いか
#enqueteは使われてるの見ないなあ。questionnaireはたまに使うと思うけど、質問紙とか質問項目のような具体的なものを指す。
#日本語で「アンケートです」みたいに使うのに一番近いのはsurveyだと思う。
#surveyそのものの意味は広いけど。
#アンケート用紙、みたいな意味の時は、Questionnaireと書いておけばいいんでしょうか
#surveyかぁ、なるほど
#「明日までにアンケート用紙用意しといてね」みたいな時はquestionnaireでいい気がする。
#「昨日もらったアンケート用紙どこやったっけ」とか。
#あと、
#「あのアンケートの項目だけどさー、偏ってるよね」とか、具体的に紙や項目が思い浮かぶ時。
#なるほど
#そこまで具体的じゃないなら全部surveyで大丈夫だと思う。
#アンケート用紙に「○○についてのアンケート」みたいにタイトルを付す場合は"survey"だと思うな。
#そういえば見たことあるかも
##Erlang使ってるらしい
#ピークだと秒当たりどのくらいになるんだろう
#均等に割ったって1万メッセージ/秒以上だからなあ
#200台で分散処理して50msg/秒
#でも、アベレージだからなぁ
#ピークだとすごいことになりそう
#分散のアルゴリズムをどうしてんのかなぁ、まさか均等にばらまいてるわけじゃあるまい...
#Erlangってメッセージは必ず1 to 1なんだっけ?
#Lindaみたいなモデルなら、複数consumerを待たせといてメッセージを投げたら暇な奴が掴むってできるけど
#それはそれでそこんとこがボトルネックになりそうだな
#宛先は1つだったと思うんですが、斜め読みで終わってるので違うのかも
#Android Marketで相場を調べようと思ったが、US or UK以外からは価格が表示されない orz
#Programming Clojure出荷通知キター(from Amazon.co.jp)
#売れるんだろうなぁ
#局所的には(笑)
#あれ、Gauche trunk、threadのテストがfailするな...(on NetBSD 5.0STABLE)
#げ、たった今コミットしたやつかな
#今っていうかさっきだけど。
#r6686
#Mac OS X 10.5.7は無問題
#うん、6686
#<basic thread API>-------------------------------------------------------------
test current-thread, expects #t ==> ok
test thread?, expects (#t #f) ==> ok
test make-thread, expects #t ==> ok
test thread-name, expects foo ==> ok
test thread-specific, expects "hello" ==> ok
test thread-start!, expects "hello" ==> ok
test thread-join!, expects 1346269 ==> ok
test thread-status, expects new ==> ok
test thread-status, expects runnable ==> ok
test thread-status, expects stopped ==> ok
test thread-status, expects runnable ==> ok
test thread-status, expects terminated ==> ERROR: GOT runnable
#最後のやつがこけてる
#あーなるほど。タイミングの問題かも。
#単なるタイミングの問題かしら
#かぶった
#ちょっとテスト直すからまってて
#らじゃ
#これでどうだ。r6687
#返ってこない...
#Testing threads ===============================================================
testing bindings in #<module gauche.threads> ... ok
<basic thread API>-------------------------------------------------------------
test current-thread, expects #t ==> ok
test thread?, expects (#t #f) ==> ok
test make-thread, expects #t ==> ok
test thread-name, expects foo ==> ok
test thread-specific, expects "hello" ==> ok
test thread-start!, expects "hello" ==> ok
test thread-join!, expects 1346269 ==> ok
test thread-status, expects new ==> ok
test thread-status, expects runnable ==> ok
test thread-status, expects stopped ==> ok
test thread-status, expects stopped ==> ok
test thread-status, expects runnable ==> ok
test thread-status, expects terminated ==>
#あれ、そもそもthread-terminate!がNetBSDでは効いてないのか?
#エラーが起こってた場所でブロックしてる気がする
#あれどうだろう
#pthread_cancel呼んでるんだけどな
#Kahuaの中でthread-terminate!を使っていたと思うので
#たぶん機能してたと思うのだけど
#自信がなくなってきた
#もしくは、pthread_cancelは効いてるんだけどpthread_cleanupによる後始末がちゃんと動いてないとかかな
#ext/threads/threads.cにstatic void thread_cleanup()って関数があるんだけど
#その入り口近く (ScmObj excの宣言のあとくらい) にprintf仕込んだらどうなるかな。
#呼ばれてはいますね
#thread_cleanup()
#あ、pthread_cancel()のあとに呼ばれてるってのは確か? 普通に終了した時もそこは通るんで…
#ちょっと待って
#vm->cancellerの値を表示してもらえばいいか。NULLでなければthread-terminate!経由
#あれ、thread_cleanup()に入った直後のvm->cancellerでいいんですか?
#はい。
#thread-terminate!経由なら、thread-terminate!がそこをセットしてるはず
#なるほど
#Testing threads ... Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 005c6c80
#ちょいと長くて失礼
#最後のを出力して止まってますね
#あ、ちゃんとthread-terminate!でやってるなあ。
#Scm_Printf(SCM_CURERR, "Info: thread_cleanup() called: vm->canceller: %08x\n", vm->canceller);
#これを ScmObj exc; の直後に挿入しました
#ちなみにそれをちょっと下の、pthread_mutex_unlock(&vm->vmlock)の下に置いても同じになる?
#if ブロックの中のやつですか?
#あ、違う勘違い
#いえ、thread_cleanup()の最後ってことです。
#最後のやつですね
#試してみます。
#念のため、cleanupは確実に済んでいるという確認
#[前略]Info: thread_cleanup() exit: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() exit: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 00000000
Info: thread_cleanup() exit: vm->canceller: 00000000
Info: thread_cleanup() called: vm->canceller: 005c6c80
#最後まで到達してないっぽい
#Scm_MakeThreadExceptionあたりで妙なエラー投げちゃってるのかな
#excの中身を表示してみる?
#いや、とりあえずScm_MakeThreadExceptionの次の行にprintfして到達してるかどうか見るとか
#ふむ
#順繰りに追っていきますか
#むー、Scm_MakeThreadExceptionの中にはエラーを投げる要素は無いなあ。
#冒頭のpthread_mutex_lock()でブロックしている疑惑
#あーでもこれって、Scm_Printf使ってるから?
#Scm_Printfでブロックしちゃったとか
#あっそうか。printfでやらないとわからないね。
#fprintfで書き直してみましたが、やはり
#if (pthread_mutex_lock(&vm->vmlock) == EDEADLK) {
Scm_Panic("dead lock in vm_cleanup.");
}
#この直後には到達しないですね
#ということは誰かがvmlockを掴んでるんだな
#自分自身ではないから、thread-join!してるほうか? でもpthread_cond_waitでロックはリリースしてるはずだが…
#ちょっと試しに、ext/threads/test.scmの方で、
#(let1 t1 (make-thread (lambda () (while #t (sys-nanosleep #e5e8))))
(test* "thread-status" 'new (thread-state t1))
(thread-start! t1)
(test* "thread-status" 'runnable (thread-state t1))
(thread-stop! t1)
(test* "thread-status" 'stopped (thread-state t1))
(thread-stop! t1) ; duplicate stop test
(test* "thread-status" 'stopped (thread-state t1))
(thread-cont! t1)
(test* "thread-status" 'runnable (thread-state t1))
(thread-terminate! t1)
(test* "thread-status" 'terminated
(guard (e [(<terminated-thread-exception> e)
(thread-state t1)])
(thread-join! t1))))
#ここの、最初の
#thread-stop!からthread-cont!までをコメントアウトして実行するとどうなる?
#(let1 t1 (make-thread (lambda () (while #t (sys-nanosleep #e5e8))))
(test* "thread-status" 'new (thread-state t1))
(thread-start! t1)
(test* "thread-status" 'runnable (thread-state t1))
; (thread-stop! t1)
; (test* "thread-status" 'stopped (thread-state t1))
; (thread-stop! t1) ; duplicate stop test
; (test* "thread-status" 'stopped (thread-state t1))
; (thread-cont! t1)
; (test* "thread-status" 'runnable (thread-state t1))
(thread-terminate! t1)
(test* "thread-status" 'terminated
(guard (e [(<terminated-thread-exception> e)
(thread-state t1)])
(thread-join! t1))))
#これでやってみたんですが
#[前略]
#Info: thread_cleanup() -->: vm->canceller: 00000000
Info: thread_cleanup() #0: vm->canceller: 00000000
Info: thread_cleanup() #1: vm->canceller: 00000000
Info: thread_cleanup() #2: vm->canceller: 00000000
Info: thread_cleanup() <--: vm->canceller: 00000000
#で、テストログは同じ
#Testing threads ===============================================================
testing bindings in #<module gauche.threads> ... ok
<basic thread API>-------------------------------------------------------------
test current-thread, expects #t ==> ok
test thread?, expects (#t #f) ==> ok
test make-thread, expects #t ==> ok
test thread-name, expects foo ==> ok
test thread-specific, expects "hello" ==> ok
test thread-start!, expects "hello" ==> ok
test thread-join!, expects 1346269 ==> ok
test thread-status, expects new ==> ok
test thread-status, expects runnable ==> ok
test thread-status, expects terminated ==>
#ふむ。いや、新しく追加したthread-stop!やthread-cont!が悪さしてないかどうかの確認。
#どうやらthread-terminate!の方みたいだねもんだいは。
#printfの出力具合が変わってるんですよ
#コメントアウトしてない時は、
#Info: thread_cleanup() -->: vm->canceller: 00000000
Info: thread_cleanup() #0: vm->canceller: 00000000
Info: thread_cleanup() #1: vm->canceller: 00000000
Info: thread_cleanup() #2: vm->canceller: 00000000
Info: thread_cleanup() <--: vm->canceller: 00000000
Info: thread_cleanup() -->: vm->canceller: 005c6c80
#あれれ、ほんとだ。
#うーむ、ちょっと本腰入れてみないとわからないかも。
#どうしましょ
#これ、わたしの自宅サーバなんですが
#何だったらアカウント作りますけど
#こっちでVMWareにNetBSD入れるのがいいかな
#ちょっと環境整えるのに時間かかるけど
#nene.kahua.org(www.kahua.org)にある公開鍵を置いておけばいいですか?
#あ、はい、入れるようにしてもらえるなら。
#メールください。IPとか
#了解です
#シェルはbashでいいですか?
#はい。
#メールしました
#mahalo
#上のテストで、thread-cont!の後に自分がthread-sleep!を呼んでtargetに起きる機会を与える、sys-nanosleepの後に(sys-close -1)を呼ぶ、と先に進みますね。netbsdのbugかなあ?
#nanosleepちゃんとcancelation pointになってないのかしらん。
#(というところで、時間切れ。afk)
#いや、cancelationの問題かとも思ったんだけれど、thread_cleanupが呼ばれてるのでpthread_cancelはちゃんと届いてるんじゃないかと。
#あれ、netbsdのgdbってスレッドデバッグどうやるんだろ
#$ gdb --version
GNU gdb 6.5
#複数スレッド走ってるはずなのにinfo threadsで何も出てこない
#うーむ。join側でpthread_cond()でmutexを開放してるのに、cleanup側のpthread_mutex_lockでブロックするなあ。なぜだ?
#ひょっとすると、最新のnetbsd-5枝先端じゃないからなのかもしれない(つまりNetBSDのバグ含み)
#ビルドはしてあるんだけど、まだインストール/再起動はしてない
#うーむ。でもenamiさんも再現できてるもたいだしな
#s/もたい/みたい/
#netbsdのバグとしても、かなり特殊な条件で出るものじゃないかな。でないと既に問題になってるでしょう。
#とりあえず小手先の調査ではわからない、というところまでわかりました。
#お、確率は低いがLinuxでも再現するぞ。
#だめだ再現確率が低すぎる。
#少し寝かせてみよう。なんか思いつくかもしれぬ。
#ostrich(自宅サーバ)に残っているshiroさん権限のgoshプロセスは殺しちゃってもいいですか?
#あ、ごめんなさい。残ってました?
#OSをアップデートします(再起動も)
#はい、killしちゃってください。
#2つ残ってますので
#了解です。
#make world開始
#こんばんわ。(び) さんと類似する件か分からないのですが FreeBSD 5.4 上で 0.8.14 で test lock and unlock - blocking (simple spin-lock) の出力をずっと待ち続けているようです。0.8.13 でも起きました。今はこのテスト項目をコメントアウトしてそのほかの試験項目をパスしたのを確認して make install して運用しています。
#(threads つながりで思いついたから書いたまでなのですが、100% 再現しますのでお役に立てることがありましたら何なりとお知らせくださいませ)
#self->pt_sleepobj = cond;
pthread__spinunlock(self, &cond->ptc_lock);
do {
self->pt_willpark = 1;
pthread_mutex_unlock(mutex);
self->pt_willpark = 0;
self->pt_blocking++;
retval = _lwp_park(abstime, self->pt_unpark,
__UNVOLATILE(&mutex->ptm_waiters),
__UNVOLATILE(&mutex->ptm_waiters));
self->pt_unpark = 0;
self->pt_blocking--;
membar_sync();
pthread_mutex_lock(mutex);
/*
* If we have cancelled then exit. POSIX dictates that
* the mutex must be held when we action the cancellation.
*
* If we absorbed a pthread_cond_signal() and cannot take
* the wakeup, we must ensure that another thread does.
*
* If awoke early, we may still be on the sleep queue and
* must remove ourself.
*/
if (__predict_false(retval != 0)) {
switch (errno) {
case EINTR:
case EALREADY:
retval = 0;
break;
default:
retval = errno;
break;
}
}
if (__predict_false(self->pt_cancel | retval)) {
pthread_cond_signal(cond);
if (self->pt_cancel) {
pthread__cancelled();
}
break;
}
} while (self->pt_sleepobj != NULL);
return retval;
}
#netbsd-5 の pthread_cond_timedwait() の後半ですが、pthread__cancelled()が最終的にcleanupを呼ぶので、
#そこでmutexをロックしたらdeadlockしますかね。
#pthread__cancelled()のほかの呼び出しではそんなロックはしていないので、ここでもunlockすべきだと思います。
#あと、nanosleep()ですが、pthread_cancelstub.c rev.1.3まではこのファイルにあってcancelされたかどうかテストしていんですが、1.4にoptimizeしたときに忘れられてそのままっぽいです。
#EDEADKにならないのはなんでかな、というのはちょっと疑問
#先日、kahuaのログが2GByteに達したところで、リクエストにうんともすんとも言わなくなる問題に遭遇しました。
#プラットフォームは、
#[bash.genkan.]$ uname -a
Linux genkan.sumibi.org 2.6.8-2-k7 #1 Tue Aug 16 14:00:15 UTC 2005 i686 GNU/Linux
#です。
#私のプラットフォーム情報もお知らせしまーす。
#zebra[Tue]$ uname -a
FreeBSD zebra.adam.ne.jp 5.4-RELEASE-p4 FreeBSD 5.4-RELEASE-p4 #0: Wed Jul 20 15:29:36 JST 2005
#kahuaのバージョンは、Kahua-1.0.7.1です。
#最近のバージョンではなおっているのかな。
#OldTypeの場合でも1年くらいで2GByte行ったみたいなので、もっとアクセスされるサイトだと寿命は短いかもしれません。
#ファイルシステムはext3ですか? >kiyoka
#たぶん最新のstable(1.0.7.3)でも変わらないはずです
#ext3の1ファイルサイズの上限って、ext2の頃と変わらんのかしら
#いずれにしても、ログライターがエラーを返した時のチェックはしてないと記憶しているので
#そこで死んでいる可能性が高いかなぁ
#ちなみにわたしが運用しているサイトのKahuaは、普通のログはnewsyslogで、stderrへの出力はmultilogでローテートしているので遭遇する機会がなかったと思われます
#ファイルシステムは ext2 ですね。
#そうすると1ファイルのサイズ上限は2GBですね
#ちゃんとログローテートしとけということですね。(笑)
#まぁそうなんだけど、それならそれで派手に悲鳴を上げて死んでくれた方がまだ状況が把握しやすいかなぁ、と
#なるほど。
#だんまりになるのはよろしくないので
#ディスクフルでも同じ現象が起きるな、きっと
#そうですね。だんまりになるので、原因を見つけるまでなかなか時間がかかりました。
#でもなぁ、stderrに悲鳴を吐くとしても、そいつをmultilogでディスクに書いてたらディスクフルには対応できない
#Apacheとかどうなるんだろ。
#syslogdとか。
#syslogdは死んでくれそうな気がする
#apacheとかは多分Disk fullとかでも、無視してリクエストは処理するんでしょうね。
#うん
#ログライターのエラーは警告だけ出して処理を続行するのが正しいかな
#Kahuaとかは1つのサーバマシンで複数立ち上げるので、ログローテション設定するのとかめんどくさいんですよね。
#自前でやった方がいい?
#でも、重くなるのがいやなんだよなぁ
#そんなにアクセスないんだったら、syslogに飛ばす設定でもいいかも。個人サイトレベルだったら。
#なるほど
#自前でやるのは、あまり好きではないです。
#私も好きじゃないです
#log4jとか。
#Javaはなんでも自前でやりすぎ。
#あんまり好きではないです。
#Lispも本来はそういう文化ですが(笑)
#まあまあまあ。
#Emacs大好き(笑)
#Kahuaのサイトバンドルごとにログローテートの設定を手で行うのは、確かに馬鹿っぽい
#昔、携帯アプリサイトの仕事をやったとき、pound(ロードバランサ)の設定で、ログの送出先をsyslogにしていたんですよ。
#うは
#取りこぼしそうだなぁ
#大量にアクセスが来て...
#UDPで飛ばしてると
#負荷もでかいし
#問題は取りこぼしではなくてですね。
#LinuxのUDPのバッファが64Kとかしかないみて
#みたいで。
#なるほど
#Webサーバの不可分散してたのに、poundでボトルネックになるという、ポカをやったことがあります。
#高負荷環境ではsyslogdは使わないのが定石ですね
#それまでUDPで送っ
#各マシンでログを書くならmultilog、集約するならsocklogかなぁ
#送っておけば無尽蔵にsyslogdが書いてくれると思っていたのでした。
#最近はsyslogもtcp接続できるものも多いんですよね。
#ありますね
#そういうオプション
#使ったことないけど
#それなら多分、UDPバッファ問題は起きなさそうですが...
#ログ書きマシンに一番強力なマシンをあてがうハメに(笑)
#UDPはパケットロスを心配する人がいますが、LANだとそんなに心配しなくてもいいんじゃないかと思いますけど。
#LANでもWANでも、受け取る側の負荷が高ければ取りこぼしますよ
#あーそうか。ブロッキングになるのはlocalhostの場合だけか...
#そういうことだったのかな。今poundの問題を理解した。
#だから、大量のログを集中管理する場合、ログを集約するマシンがクリティカルポイントになることがあるわけです
#なるほど。
#わたしは割とそれがいやで、各マシンにログを吐いて、定時処理でどこかに集約するとかって仕組みにすることが多かったです
#ログって難しいですね。とくにパフォーマンス計測用ログとか。元の処理に影響を与えてしまう。
#そうなんですよね
#ロギングそのものがI/Oという重い処理をともなうので
#観測対象に与える影響が無視できなくて
#ちゃんと考え始めるとけっこう難しい
#最近はあんまり考えないですけど(ぉぃ)
#そうですね。バグが出てからとかパフォーマンス問題が出てから、やっと本気で考え始める。
#SSDとかだと書き込み負荷が軽減できたりするんでしょうかね。
#ちゃんと調べてないんですが、SSDって「一瞬固まる」問題があるらしいので
#SSD上にリングバッファ的に直近1日分くらい出力しておいて、夜間だけDISKに出すとか。
#用途によってはそれがマズい場合もあるかなぁ
#やっぱりそうなんですか。
#じゃあやっぱりでかいRAMですか。
#TokyoCabinetとTokyoTridentだったっけ。
#それならRAMディスクに書いて定期的にディスクに吐くとかでもいいかも
#そんな組み合わせですか。あまり詳しくないですけど。
#TokyoCabinetってdbmだよね?
#そうですね。
#qdbmの後継
#さすがに追記一辺倒の用途だったらプレーンテキストでぶつ切りにした方がよさげ
#TokyoTridentは知らないや
#TokyoTylantだった。
#tyrant?
#暴君
#TokyoTyrantか
#凶暴そうだ(笑)
#暴君ハバネロみたい。
#ネタで東京暴君というDBサーバ作って暴君ハバネロのパッケージみたいなトップページにするとよい。
#エイプリルフールネタですね。これ。
#眠い... さすがに限界
#おやすみなさい
#おやすみなさい。
#PTHREAD_MUTEX_NORMALだったらEDEADLKにはならないか。
#NetBSDでの動作は、NetBSDのbug二つで説明つきそう
#ふーむ。これはpthread_cond_waitにcancellationが絡むというケースだから?
#さらにcleanupが絡んででるbugですね
#cancellationがなければ、thread.cのmutexとcondition variableの使い方は教科書的であってまだバグが残ってるとは考えにくいので
#ああなるほど。cleanupもか。
#pthread_cond_waitの中でcancelされたとき、渡されたmutexをlockしたままcleanup handler呼んじゃってます(bug-1)
#(thread-cont!の後にthread-sleep!するなどして)pthread_cond_waitの外でcancelされると、nanosleepが正しくcancelation pointになっていないので、cancelできない(but-2)
#(1) bug-1は、cancellation typeがDEFERREDでも出ますか? async cancelaltionはもともと危険な操作なので推奨されてない(からバグも見つかってなかった)のかも。
#(2) bug-2は、async cancellationでもcancelできないってことですか。
#(2)はyes, (1)はsource読まないとわからないけど、ちょっとafkするので、後で。