Activity, over time
Daily observations from the public event archive.
Attention
Daily stars & forks
Star accumulation
Cumulative stars
Pull requests
Daily opens & merges
Conversations
Daily issues & comments
Community
Daily accounts & reviews
Releases
Daily releases
Trending history
Daily top 10 · last 90 days · UTC
Mentions
Stars
Forks
Contributors
Latest stargazers
The last 10 distinct accounts we observed this year.
Most active participants
PR, issue, comment & review events in the past year.
Packages
Scan pending.
Live mentions badge
Show how many posts mention your project in the last 30 days.
Live mentions · last 30 days
Mentions
Nim の Boehm GC で、落ちるはずのプログラムが 90 分固まっていた --mm:boehm でビルドした Nim のプログラムは、Boehm GC の中で致命的なシグナルが起きると、終わらずに固まっていました。この問題を直した PR(#26515)が、10 月 22 日に Nim の devel にマージされました。今は、メッセージを出してすぐに終わります。この記事では、なぜ固まっていたのか、何を変えたのか、何と引き換えにしたのかを書きます。 CI が 90 分止まった きっかけは CI です。tests/gc/gctest.nim を --gc:boehm で走らせるジョブが、3 回続けて 90 分の上限まで止まったままになりました。原因の一つは二重解放で、それは別の PR(#26506)で直っています。ただ、二重解放ならすぐに落ちるはずです。90 分も固まったのは、別の問題でした。 シグナルハンドラが、自分の持つロックを待っていた 固まった実行に gdb を当てると、シグナルハンドラの中で止まっていました(devel 9f769b15、Debian 12 arm64、libgc 8.2.2)。 #1 pthread_mutex_lock #2 GC_disable (libgc) #3 GC_disable_u0__system #4 signalHandler #5 <signal handler called> #7 raise #8 abort #9 ?? (libgc) #10 GC_free (libgc) 流れは次のとおりです。 Boehm の GC_free が不正な解放(Duplicate large block deallocation)に気づき、アロケータのロックを持ったまま abort を呼ぶ。 Nim の signalHandler が動き、スタックトレースを書く前に GC_disable と newStringOfCap を呼ぶ。 どちらも同じロックを取りにいくが、そのロックは同じスレッドが持ったままなので、永遠に待つ。 signalHandler の上には、もともと「アロケーションの最中にシグナルが来るとここで壊れうる」というコメントがありました。Boehm の場合、その壊れ方が「落ちる」ではなく「固まる」だったわけです。CI にとっては、固まるほうがずっと困ります。ジョブが時間切れになるまで、何も分からないからです。 何を変えたか Boehm のときは、signalHandler がスタックトレースを書かず、メッセージだけを書いて終わるようにしました。 新しい経路は足していません。signalHandler には、スタックトレースを持たないビルドのための「メッセージだけを書く」分岐が既にあります。Boehm のときもそちらを通るように、when の条件を 1 つ変えただけです。Boehm を使わないビルドでは、生成されるコードは前と同じです。 PR のときに Debian 12 arm64(libgc 8.2.2)で確かめた結果は次のとおりです。大きなブロックを 2 回解放するテスト(tests/gc/tboehm_signal.nim)で比べました。 結果 修正前 何も出力せずに固まる。テストに仕込んだ alarm(30) で 32 秒後に打ち切られた 修正後 1 秒で SIGABRT: Abnormal termination. を出して終わる testament cat gc は 79/79 で、gctest の Boehm の 2 つの実行も通りました。 引き換えにしたもの Boehm でビルドしたプログラムは、シグナルを受けたときにスタックトレースを出さなくなりました。Boehm の中のシグナルだけでなく、nil の参照外しのような普通のシグナルでも同じです。ほかのメモリ管理(ORC、ARC、refc)は変わりません。 この修正は devel に入りました。リリースされている版(2.2 系)への backport は、今のところ決まっていません。 テストに仕込んだ alarm と、testament のもう一つの問題 上の表の「alarm(30) で打ち切られた」には理由があります。Nim のテストランナー(testament)は、テストの spec に上限時間(timeout)を書いても、プロセスが終わった後に経過時間を比べるだけです。止まったテストを打ち切りません。そのため、固まるテストを testament に普通に渡すと、それ自体が CI を上限まで止めてしまいます。テストの中で alarm を仕込んだのは、そのためです。 今回 90 分待たされたのは、これも理由の一つです。テストが固まっても、どのテストが固まったのかは、ジョブの上限が来るまで分かりませんでした。同じ問題の issue は、2021 年(#17407)と 2024 年(#24278)に出ていて、どちらも開いたままです。 上限時間を過ぎたテストのプロセスを打ち切り、reTimeout として報告する修正を手元で作りました。macOS arm64 と、Linux の arm64(glibc)と amd64(musl)で、止まるテストが数秒で打ち切られることを確かめてあります。今出している PR の結果を見てから、出す予定です。