**Show HN:**

*Deadlog – Go のデッドロックをデバッグするためのほぼ即座に使用できるミューテックス*

2026/02/11 2:44

**Show HN:** *Deadlog – Go のデッドロックをデバッグするためのほぼ即座に使用できるミューテックス*

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

改善された要約

Deadlog は軽量な Go ライブラリで、標準の

sync.Mutex
/
sync.RWMutex
をデバッグ有効版(
deadlog.Mutex
)に置き換えます。インストールは次のように行います:

go get github.com/stevenctl/deadlog

そして、名前付きミューテックスを作成して使用します:

m := deadlog.New(deadlog.WithName("my-service"))

API は

sync.Mutex
/
sync.RWMutex
と同等で、
Lock()/Unlock()
および
RLock()/RUnlock()
を提供します。さらに、開発者は
LockFunc()
または
RLockFunc()
を呼び出すことで「RELEASED」イベントを発行するアンロック関数を取得できます。ロック操作にはラベル付け(
WithLockName("name")
)やスタックトレースの深さ調整(
WithTrace(n)
)が可能です。

デフォルトでは、ログは JSON 形式で stdout に書き込まれます。カスタムロギングは

deadlog.WithLogger()
または
deadlog.WriterLogger(f)
を使用してサポートされます。ログエントリには次のフィールドが含まれます:
type
(LOCK、RLOCK、WLOCK、RWLOCK)、
state
(START、ACQUIRED、RELEASED)、
name
id
ts
およびオプションでスタックトレース。

CLI 分析ツールは次のようにインストールできます:

go install github.com/stevenctl/deadlog/cmd/deadlog@latest

そして次のように使用します:

deadlog analyze file.log

分析器は、すべてのタイプで「START だけが ACQUIRED されていない」スタックロック(stuck locks)と、トラッキングされたタイプ(

LockFunc
RLockFunc
)に対してのみ「ACQUIRED だけが RELEASED されていない」保持ロックを特定します。分析ライブラリ(
github.com/stevenctl/deadlog/analyze
)はこの機能をプログラム的に公開しています。

Deadlog は MIT ライセンスの下で配布されています。将来の拡張として、より豊富なロックタイプ追跡、観測スタックとの緊密な統合、および深い事後調査のための CLI 機能拡張が予定されています。

本文

deadlog(デッドロック検出ツール)

Go 用のライブラリで、ミューテックスのデッドロックをログ付きラッパーと解析ツールでデバッグできます。


インストール

go get github.com/stevenctl/deadlog

使い方

sync.Mutex
または
sync.RWMutex
deadlog.Mutex
に置き換えます:

import "github.com/stevenctl/deadlog"

// Before
var mu sync.RWMutex

// After
var mu = deadlog.New(deadlog.WithName("my-service"))

API は

sync.Mutex
sync.RWMutex
の両方に互換性があります。

ロック操作

// 書き込みロック(sync.Mutex と同等)
mu.Lock()
defer mu.Unlock()

// 読み取りロック(sync.RWMutex と同等)
mu.RLock()
defer mu.RUnlock()

未解放ロックの追跡

LockFunc()
RLockFunc()
を使うと、関連付けられた RELEASED イベントを取得できます:

unlock := mu.LockFunc()
defer unlock() // 同じ correlation ID で START, ACQUIRED, RELEASED がログに残ります

名前付き呼び出し元

同一ミューテックス上の個別ロック操作にラベルを付けます:

mu := deadlog.New(
    deadlog.WithName("player-state"),
    deadlog.WithTrace(1),
)

// 各呼び出し元はログで独自の名前が表示されます
unlock := mu.LockFunc(deadlog.WithLockName("update-health"))
defer unlock()

WithTrace(1)
と組み合わせると、JSON イベントに正確な位置情報が付与されます:

{"type":"LOCK","state":"START","name":"update-health","id":4480578,"trace":"updateHealth:25","ts":1770746273707970140}
{"type":"LOCK","state":"ACQUIRED","name":"update-health","id":4480578,"trace":"updateHealth:25","ts":1770746273707993939}
{"type":"LOCK","state":"START","name":"add-item","id":9375956,"trace":"addItem:29","ts":1770746273707996887}
{"type":"LOCK","state":"ACQUIRED","name":"add-item","id":9375956,"trace":"addItem:29","ts":1770746273707998734}
{"type":"LOCK","state":"START","name":"apply-damage","id":6439038,"trace":"applyDamage:33","ts":1770746273708002604}

解析ツールはこれをわかりやすいレポートに変換します — apply‑damage が待機中で、update-healthadd-item がロックを保持しています:

===============================================
  LOCK CONTENTION ANALYSIS
===============================================

=== STUCK: Started but never acquired (waiting for lock) ===
  LOCK  | apply-damage         | ID: 6439038
         Trace: applyDamage:33

=== HELD: Acquired but never released (holding lock) ===
  LOCK  | update-health        | ID: 4480578
         Trace: updateHealth:25
  LOCK  | add-item             | ID: 9375956
         Trace: addItem:29

=== SUMMARY ===
  Stuck waiting: 1
  Held:          2

スタックトレースの取得

ロック取得場所を確認したい場合は、スタックトレースを有効にします:

mu := deadlog.New(
    deadlog.WithName("my-mutex"),
    deadlog.WithTrace(5), // 5 フレーム深さで取得
)

カスタムログ

デフォルトではイベントは JSON として stdout に書き出されます。カスタムロガーを指定することも可能です:

mu := deadlog.New(
    deadlog.WithLogger(func(e deadlog.Event) {
        log.Printf("[DEADLOG] %s %s %s id=%d", e.Type, e.State, e.Name, e.ID)
    }),
)

または特定の writer に書き込むこともできます:

f, _ := os.Create("locks.jsonl")
mu := deadlog.New(deadlog.WithLogger(deadlog.WriterLogger(f)))

解析

CLI ツール

CLI をインストールします:

go install github.com/stevenctl/deadlog/cmd/deadlog@latest

ログファイルを解析します:

deadlog analyze <file>

またはアプリから直接パイプで渡すことも可能です:

go run ./myapp 2>&1 | deadlog analyze -

ライブラリ

プログラムから解析ライブラリを使う場合:

import "github.com/stevenctl/deadlog/analyze"

result, err := analyze.AnalyzeFile("app.log")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Stuck: %d, Held: %d\n", len(result.Stuck), len(result.Held))

// フォーマット済みレポートを出力
analyze.PrintReport(os.Stdout, result)

ログ形式

イベントは JSON で記録されます:

{"type":"LOCK","state":"START","name":"my-mutex","id":1234567,"ts":1704067200000000000}
{"type":"LOCK","state":"ACQUIRED","name":"my-mutex","id":1234567,"ts":1704067200000001000}
{"type":"LOCK","state":"RELEASED","name":"my-mutex","id":1234567,"ts":1704067200000002000}
フィールド説明
type
ロック種別(下記参照)
state
START
,
ACQUIRED
,
RELEASED
のいずれか
name
WithName()
で設定したミューテックス名
id
相関 ID(ランダム、同じロック操作の START/ACQUIRED/RELEASED で共通)
ts
Unix ナノ秒タイムスタンプ
trace
スタックトレース(
WithTrace()
有効時のみ)

ロック種別

メソッドtypeTracked?説明
LockFunc()
LOCK
はい書き込みロック(RELEASED を追跡)
RLockFunc()
RLOCK
はい読み取りロック(RELEASED を追跡)
Lock()
WLOCK
いいえ書き込みロック、RELEASED イベントなし
RLock()
RWLOCK
いいえ読み取りロック、RELEASED イベントなし

Tracked な種別 (

LOCK
,
RLOCK
) は unlock 関数で RELEASED を発行するため、解析ツールは保持中のロックを検知できます。Untracked 種別 (
WLOCK
,
RWLOCK
) は
sync.Mutex
/
sync.RWMutex
と同等に使えますが、RELEASED イベントがないので「保持」として報告されません。

最初は untracked メソッドで競合を検出し、必要に応じて tracked メソッドへ切り替えてどのロックが保持されているかを特定します。

動作原理

フェーズ説明
START
ロック取得を試みる直前にログ
ACQUIRED
ロック取得後にログ
RELEASED
unlock 関数呼び出し時にログ(
LockFunc()
/
RLockFunc()
のみ)

解析ツールは次の状態を検知します:

  • Stuck
    START
    があるが
    ACQUIRED
    がない(ゴルーチンがロック待ち中) – すべての種別で対象
  • Held
    ACQUIRED
    はあるが
    RELEASED
    がない(ロックが解放されていない) – tracked 種別 (
    LOCK
    ,
    RLOCK
    ) のみ

ライセンス

MITライセンス
MIT LICENSE

同じ日のほかのニュース

一覧に戻る →

2026/02/16 6:54

OpenAI に入社いたします。

## Japanese Translation: ** ## Summary: 著者は、OpenAIに参加する計画を発表しつつ、自身のオープンソースプロジェクト **OpenClaw** の開発を継続することを示しています。OpenAI のリソースとスポンサーシップと連携することで、ユーザーに優しく安全な AI エージェントをより広い層へ届けることを目指しています。彼らのプレイグラウンド・イニシアティブはすでに世界的な注目を集めており、アクセスしやすいツールの価値を証明しました。サンフランシスコで主要研究所と会議を行い、最先端モデルへの早期アクセスを得た一週間後、著者は OpenAI の高度な技術とオープンソース基盤を組み合わせることが責任ある AI 展開に不可欠だと考えています。 今後、OpenClaw は多様なモデルをサポートし、コミュニティ協力を奨励するファウンデーションへ進化します。著者は OpenAI の最前線研究チームに直接貢献すると同時に OpenClaw を独立して維持し、急速な商業スケールよりもインパクトのある製品に焦点を当てます。この二重アプローチは、非技術的ユーザーに強力なエージェントを提供し、開発者やデータ所有者に柔軟な基盤を構築させ、AI 業界を研究と実世界応用を橋渡しするより強固なオープンソース基盤へとシフトさせる可能性があります。

2026/02/16 2:12

LT6502:6502ベースの自作ラップトップ

## Japanese Translation: ``` ## Summary この設計は、8 MHz 65C02プロセッサを中心に構築されたコンパクトでバッテリー駆動のコンピュータを概説しています。 メモリ:46 KB RAM(0x0000–0xBEAF)はゼロページ、BASIC RAM、および Compact Flash バッファに分割されます;EhBASIC 2.22p5 と eWozMon およびブートストラップコードは ROM の 0xC000〜0xFFFF に配置されています。 周辺機器:タイマー/IO 用の 65C22 VIA(0xBFCO)、Compact‑Flash コントローラ(0xBFBO)、ビーパー(0xBFA0)、内部キーボード(0xBFEO)、コンソール FTDI インターフェース(0xBFF0)があります。 ディスプレイ:9″ RA8875 パネル(800×480)に内蔵フォントとシンプルなグラフィックスがあり、開発時には 4.3″ デモユニットも使用されました。 インターフェース:`OUTK` コマンド用の 8文字 OLED キーボード、USB‑C 充電/電源供給、シリアルコンソールアクセス、および将来のボード用に 0xBE00 に拡張スロットがあります。 バッテリー:**10 000 mAh** パック(USB‑C で電源・充電)。 ファームウェアは、BEEP、CIRCLE、CLS、COLOUR、DIR、ELIPSE、LINE、LOAD、MODE、OUTK、PLOT、SAVE、SQUARE、および WOZMON などのカスタム EhBASIC コマンドを追加します。 開発マイルストーン: - PCB スキーマティクスは 2025‑11‑12 に完成。 - 電源投入と基本機能は 2026‑01‑05 に達成。 - CF コントローラとビーパーは 2026‑01‑09 に動作確認済み。 - ディスプレイ統合は 2026‑01‑16 に完了。 - ファームウェア拡張(SAVE/LOAD、グラフィックス)は 2026‑02‑08 後から進行中。 - ケース組立は 2026‑02‑14 に完了。 このプロジェクトは、BASIC 開発者と教育者向けに低価格で携帯性の高いプラットフォームを提供し、レトロコンピューティングコミュニティおよび組込みシステム教育への影響が期待されます。 ```

2026/02/16 5:53

**GNU Pies ― プログラム起動と実行監視**

## Japanese Translation: **改訂された概要** Pies は軽量なスーパーバイザーで、外部プログラム(「コンポーネント」)を起動・監視し、自動的に再起動します。各コンポーネントはフォアグラウンドで実行され、Pies は起動時に設定ファイルからそのリストを読み込みます。コンポーネントの起動後、Pies はバックグラウンドプロセスとして継続し、終了を監視します。デフォルトでは予期せず停止したコンポーネントを自動的に再起動します。また、終了時にメール通知を送信したり別のプログラムを呼び出すなど、代替アクションを設定することも可能です。GNU ライセンスで提供される Pies は init デーモン(ブート時に最初に起動されるプロセス)として機能できます。この役割では、従来の `/etc/inittab` ファイルまたは Pies 独自の GNU スタイル設定を通じて構成を提供でき、古い init システムよりも柔軟性が高くなります。制御インターフェースは既に管理対象コンポーネントに対して広範囲な監視と管理機能を提供しています。

**Show HN:** *Deadlog – Go のデッドロックをデバッグするためのほぼ即座に使用できるミューテックス* | そっか~ニュース