Posts for: #Debug

openldap サーバーのデバッグ

1時に寝て3時に起きて5時に起きて6時半に起きた。あとひと踏ん張りなのでこのまま突っ切る。

openldap 2.5 の ldappasswd の振る舞い

openldap サーバーでパスワードを変更時の平文パスワードを連携するために カスタム overlay モジュール を使っている。前回の改修をしたときは openldap 2.4 向けのみの振る舞いを検証していた。今回は開発フェーズでは openldap 2.5 向けにもモジュールをビルドしてパッケージングしていた。その qa テストをしていて ldappasswd だけ、意図したパスワード連携が行われないという。

開発時に私が振る舞いを検証したつもりが ldapadd, ldapmodify は確認済みだったが、ldappasswd の確認をしていなかった。これは完全に私のミスで2つのフックポイントに対してカスタム overlay モジュールが動くのだから ldappasswd も大丈夫だろうと見通していた。しかし、そうではなかった。それぞれにフックポイントのコールバック設定があって、フックポイントもロジックが違うのだから当然ではあるのだけど、ちゃんと動作検証をしないといけないという、初歩的なミスをした。こんなこともあるんやと反省した。

gdb でデバッグしていて原因は 2.5.3 に含まれる次の修正だとわかった。私が検証していた openldap サーバーのバージョンは 2.5.14 だった。

簡潔に言えば、なんらかの不具合対応でもともと設定してあるコールバックを別のものに上書きしていた。カスタム overlay モジュールが設定したコールバックが別のものに上書きされてしまって意図した振る舞いをしないという現象が起きていた。これは明らかに openldap のリグレッションなので 2.5.15 で修正されてた。

たまたまピンポイントにバグを踏んだ形にはなったが、qa テストという別の人がテストをする仕組みでこのバグを検出できたことがうちの開発の品質基準を担保していることの表れでもある。

生きるということは嬉しいこと半分、辛いこと半分なのですよ。 采王

1行のミスによる1行の修正

0時に寝て何度か起きて6時半に起きた。朝から外はめっちゃ暑い。冷房をつけっぱなしのオフィスも朝からやっぱり暑い。根本的な空調の問題。

agent アプリケーションのメモリリーク正体

先週のメモリリーク調査 の続き。本当は週末にやればよかったんだけど、遊んでたりさぼってたりして放置してた。先週時点でリークしているのは go-zeromq/zmq4 側だというのはわかっていたが、何が原因でリークしているのかは分からなかった。一通りソースも読んでみたけど、いまひとつよく分からない。仕方ないから動的デバッグでソースコードに手を入れながら調査していて、すぐにみつけた。socket 構造体が保持しているコネクションの map がどんどん肥大化していく。なにも使っていない map にコネクションの値を保持して解放する処理がないことに気付いた。

sck.ids[uuid] = c

修正するかと思ってリポジトリの最新ブランチをみてもそのコードが見当たらない。すると次の pr で4月に修正されていた。まだリリースされていないからうちらのアプリケーションで使っているリビジョンにはその修正が含まれていなかった。

Additionally, remove sck.ids, which is unused and leaks *Conn.

メモリリークの調査を始めたときに github issues/pr を leak で検索して一通りチェックしているので、先週もこの pr をみかけているはずだが見逃してしまった。タイトルが全然違うし、ほんの1行の typo に近いミスなので修正内容をみて気付かなかったのだと思う。自分の観察力の無さに気付いた。leak で検索ヒットしているのだから、それが自分たちのアプリケーションで使っているコードに入っているのかどうか、その内容をもっと注意して調べるべきだった。そうすればこの調査時間を数時間は短縮できた。これは私のミスだと認めて Postmortem のラベルを付けた。次回の定例会議でふりかえりに使う。

c 言語の開発は chatgpt と共に

1時に寝てやや吐き気で起きて休憩して3時ぐらいに寝たか寝てないかわからないうちに8時に起きた。ジンをたくさん飲んで帰ってきたのでうまく眠れなかった。

カスタム overlay モジュールの改修

OpenLDAP Overlays という機能がある。以前 ppolicy_hash_cleartext と カスタム overlay モジュール を組み合わせると ppolicy が平文パスワードをハッシュ化してしまって、自分たちのカスタム overlay モジュールから平文パスワードを取得できないことをデバッグで検証した。ppolicy_hash_cleartext の機能が必要なのかどうかが私はよくわかっていないけど、協調して自分たちのカスタム overlay モジュールが動くならそれに越したことはない。

gdb でデバッグして振る舞いと対応方法が分かったところで issue を作成していた。メンバーが暇だったらやってくれるかな?と思っていたら誰も手をつけないみたいなので私がやろうと決めた。最早、私は c 言語をなんも分からんのやけど、chatgpt に質問しながら教えてもらえる。例えば、c 言語についてもこんな感じにヒアリングしながら実装する。

Q. c 言語で関数の最初に変数を宣言するのと、実際に変数を割り当てるところで宣言するのでなにか振る舞いが違ったりしますか?どちらの方がよいのでしょうか?

C言語は伝統的に変数のスコープとライフタイムを管理するために、ブロック(通常は関数または制御構造内)の先頭で変数を宣言するスタイルを採用してきました。しかし、C99標準以降では、変数はその使用が初めて必要となる場所で宣言できるようになりました。 これら2つのスタイルの違いは、主にスコープ、可読性、そしてある程度はパフォーマンスに関連しています。

スコープとライフタイム

関数の先頭で変数を宣言すると、その変数は関数全体で使用できます。これは必要に応じて変数を再利用できるという利点がありますが、一方でスコープが広くなりすぎて変数の使用を追跡しにくくなるという欠点もあります。 一方、変数を使用が必要となる場所で宣言すると、その変数のスコープとライフタイムはその場所からブロックの終わりまでに制限されます。これは、変数の使用をより明確にし、未使用の変数を避けるという利点があります。

可読性

変数を使用が必要となる場所で宣言すると、その変数の目的と使用方法がより明確になるため、コードの可読性が向上することが多いです。一方で、関数の先頭で変数を一括して宣言すると、変数の目的が明確でない場合や、それらがどのように使用されるのかを追跡するのが難しくなることがあります。

パフォーマンス

パフォーマンスについては、現代のコンパイラは非常に高度に最適化されているため、変数の宣言場所がパフォーマンスに直接的な影響を及ぼすことはほとんどありません。

結論

どちらのスタイルを選ぶかは、主にプログラミングスタイルやチームのコーディング規約、または特定のタスクに対する特定の要件に依存します。しかし、変数を使用が初めて必要となる場所で宣言するスタイルは、コードの可読性を向上させ、変数のスコープとライフタイムを制限するという利点から、一般的には推奨されています。これにより、コードの可読性が向上し、変数の使用範囲が明確になるため、コードの理解と保守が容易になります。

そっか。C99 で変数宣言の制約が撤廃されたんだということを学んだ。そんな感じで openldap についても chatgpt にヒアリングしながら開発したら意外とすんなり実装できてローカルでは動いた。レビューまでできた。

カスタム overlay モジュールを完全にマスターした

0時に寝て何度か起きて7時に起きた。変な夢をみた気がするが、どんな夢だったかは思い出せない。

openldap のカスタム overlay モジュールのデバッグ

先週末から openldap のカスタム overlay モジュール の開発やデバッグをしている。openldap のソースコードや gdb のデバッグのやり方にも慣れてきて私の中でも理解度が増してきた。

openldap サーバーのデバッグログは次のコードが設定されている。

#define LDAP_DEBUG_TRACE  0x0001

このコードを slapd.conf の loglevel に設定するとデバッグログを出力できるようになる。

loglevel stats 0x0001 ...

このときに ppolicy の overlay モジュールがどのタイミングで呼ばれるかをデバッグログを確認しながら検証した。

overlay ppolicy
ppolicy_hash_cleartext on

結論から言うと次の2点になる。

  • overlay は slapd.conf の後ろに書いた方のカスタムモジュールが先に実行される
  • ppolicy_hash_cleartext は ppolicy_add のタイミングで平文パスワードをハッシュ化している
    • gdb でデバッグすると op->o_request->oq_add->rs_modlist も op->o_request->oq_add->rs_e->e_attrs も同じアドレスを指す
    • overlay の処理は db に書き込む前と後の2つのタイミングがある
slap_passwd_hash( &(pa->a_vals[0]), &hpw, &txt );
...
pa->a_vals[0].bv_val = hpw.bv_val;
pa->a_vals[0].bv_len = hpw.bv_len;

カスタム overlay モジュールを使って openldap からパスワードを取得するには次の順番で処理が行われることを理解しておく必要がある。

  1. mycustom_add <= このタイミングで平文パスワードを取得しないといけない
  2. ppolicy_add <= このタイミングで平文のパスワードをハッシュ化する
  3. mycustom_add_response <= このタイミングではすでにパスワードがハッシュ化されている

openldap のことを何も知らない素人が chatgpt と一緒にデバッグしてこのことを2日で理解できた。開発のやり方が変わっていく予兆を感じた。

休出デバッグ

昨日は久しぶりに飲みに行っきて1時に寝て8時に起きた。

ストレッチ

外がだいぶ暖かくなってきて散歩に行く機会も増えてきた気がする。今日の開脚幅は開始前157cmで、ストレッチ後159cmだった。先週と違って今週は忙しくて座っている時間が大幅に増えた。そして、その分の右腰の張りは強かった。腰の張り具合はその週の忙しさや労働時間で推測できるぐらいにはわかってきた。それ以外はだいたい可もなく不可もなくな感じだったと思う。

淡路牛の受け取り

姉からお肉が届くという連絡があったので日時を調整して受け取った。島サラダフェア2022 という懸賞に応募していたのが当たったらしい。5000円相当の淡路牛らしい。お正月に食べるようなお肉だと言えば伝わるかな。A賞の5名のうちの1人がここにいるので総応募数は推して知るべし。姉が言うには全然応募ないらしい。こういうの調べて真面目に応募してメルカリで売るみたいなことやったらそれなりに儲かるのかもしれない。運営はマーケティングのやり方を変えた方がいいんじゃないかとか心配になって話していた。

openldap の overlay のデバッグ

午後から昨日の続き。chatgpt と一緒に openldap サーバーのカスタム overlay モジュールのデバッグをしていた。昨日の時点では2つの問題があることを確認できていた。今日は個々の問題の詳細をデバッグしながらワークアラウンドとして動かすためのコードを書いた。1つはビルドの問題じゃないかと思える不可思議な現象が起きていて、もう1つは openldap の ppolicy の仕様とカスタム overlay モジュールの仕様のどちらが正しいのかを設計者に確認する必要がある。15年ぶりぐらいに c 言語のコードを書いている。かなり怪しいけど、gdb をインタラクティブな repl のようにして振る舞いを確認しながら書いている。カスタム overlay モジュールでエラーが発生すると openldap はその処理をスキップするようにみえて、なんのログも出ない。細かくログ出力してどこまで動いたのかを確認しながら開発するとよさそうな雰囲気がわかった。

oss な開発は chatgpt が猛威を振るう予感

2時に寝て6時半に起きた。開発の追い込みが佳境に入ってきて集中力が増してきた。

chatgpt と一緒にデバッグ

openldap サーバーの拡張の仕組みに Overlays がある。c 言語でカスタム overlay を実装することで openldap サーバーに任意のフック処理を実装できる。いまやっていることはパスワードの追加や更新をフックしてそのパスワードを id 連携するためのモジュールを開発している。というか、開発済みだと聞いていたモジュールが意図したように動かないのでデバッグしている。例えば ppolicy という overlay を使って次のように設定すると、平文で送ったパスワードをディレクトリサービスの db へ格納する前に平文からパスワードをハッシュ化してくれる。この変換はパスワード変更を overlay でフックして実装されている。

overlay ppolicy
ppolicy_hash_cleartext on

overlay は slapd.conf に設定した順番に実行されるようで、それぞれの overlay に依存関係がある場合は実際の処理にも影響がある。そんな openldap サーバーの拡張モジュールの開発を引き継ぐことになったが、私がまったく openldap サーバーのことをわかっていないので chatgpt を使って理解しながらデバッグしている。これがそれなりにうまくいっていて調査が捗った。但し、chatgpt が教えてくれたことなので完全に正しいかどうかの保証がない。振る舞いで検証できるものはともかく、そうじゃないものは最後に有識者に正しいかどうかを確認する必要がある。

例えば、次のような ldif エントリーをサンプルとして、パスワードは userPassword という属性で扱う。ここで userPassword だけコロンが2重 (::) になっていることがわかる。これは属性の値が base64 でエンコーディングされていることを意味している。こういった2重コロンのような短いキーワードを検索で調べるのは難しい。chatgpt ならピンポイントに答えてくれる。

dn: uid=jdoe,ou=users,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: jdoe
cn: John Doe
givenName: John
sn: Doe
mail: jdoe@example.com
userPassword:: e1NTSEF9bm9ZMU5kdzN3WUdSbFhpdDJUaTY5UW9SeXpXaklEeXc=

openldap は oss だし、ドキュメントもインターネット上にあるので構造体の定義や c 言語のサンプルコードも書いてくれる。それらが完全に正しいか、私には判断できないが、openldap のソースコードで調査するところの当たりをつけるには十分な情報を返してくれる。カスタム overlay を開発するときの主要なエントリーポイントと ldap 操作のタグ名は次になる。

  • bi_op_bind: バインド(認証)操作に対応するエントリーポイント、LDAP_REQ_BIND
  • bi_op_search: 検索操作に対応するエントリーポイント、LDAP_REQ_SEARCH
  • bi_op_compare: 比較操作に対応するエントリーポイント、LDAP_REQ_COMPARE
  • bi_op_modify: 修正(属性の追加、削除、変更)操作に対応するエントリーポイント、LDAP_REQ_MODIFY
  • bi_op_modrdn: エントリ名の変更 (MODIFY RDN) 操作に対応するエントリーポイント、LDAP_REQ_MODRDN
  • bi_op_add: エントリの追加操作に対応するエントリーポイント、LDAP_REQ_ADD
  • bi_op_delete: エントリの削除操作に対応するエントリーポイント、LDAP_REQ_DELETE
  • bi_op_abandon: 中止操作に対応するエントリーポイント、LDAP_REQ_ABANDON
  • bi_op_extended: 拡張操作に対応するエントリーポイント、LDAP_REQ_EXTENDED

例えば、LDAP_REQ_ADD は ldap.h で次のように定義されている。

#define LDAP_REQ_ADD        ((ber_tag_t) 0x68U) /* application + constructed */

これを gdb でデバッグしてタグを確認するときは次のように Operation 構造体内の o_tag をチェックすればよい。gdb で16進数表示するときは /x を指定する。

(gdb) print /x op->o_tag
$8 = 0x68

ppolicy よりも前にカスタム overlay を設定すれば平文のパスワードにアクセスできそうにみえるのだけど、gdb でデバッグしているとハッシュ化済みのパスワードになっていた。

あと稼働している openldap サーバーに gdb で attach してデバッグする方法も chatgpt に聞きながら行った。やりたい操作に対して gdb のコマンドを教えてもらってすぐに検証してフィードバックからさらに質問できるのでインタラクティブな repl のような環境と chatgpt は相性がよいように思えた。gdb のコマンドを覚えておく必要も、ググる必要もないことに気付いた。

近況報告

元同僚と 約1年ぶりの近況報告 の雑談会をしてきた。これで3回目かな。毎年の恒例行事のようになってきた。兵庫県の住みたい街ランキングでいつも上位にある 西宮市 でカレーを食べて、バーで飲んできた。三ノ宮から西宮は快速で15分程度の距離。すぐ行ける場所なんだが、とくに行く機会がなかったので神戸に引っ越してきて5年以上経つのに電車で行ったのは今回が初めてになる。いつも通り近況を聞きながら、みんな私と同じぐらいの世代なので今後のキャリアの方向性などを話していた。

私は起業して税金やその仕組みに関心をもつようになり、起業する前より少し詳しくなった。知人から節税相談を受けることもある。税金の基本的な考え方として、1つの大きな収入に対して節税することはできない。自由に使えるお金がほしかったら基本的に節税できない。税金をたくさん払って貯金するしかない。一方で個人と会社に資産を分割したり、共済や基金を活用することで手取りの収入は減るが、支払う税金は少なくなって中長期でみると資産が増える。例えば、共済や基金に積み立てたお金は原則としては退職所得で戻ってくるので、ずっと優遇された 退職所得の所得税 により、最終的に支払う税金が少なくなるからである。これが税金を支払う基本的な考え方。自分の手元にお金を残した上で税金を払いたくないが、どうすればよいか?とよく聞かれるが、そんなことはできないというのが模範回答になる。元同僚も私もそうなのだが、もはや自分の生活にお金をあまり必要としていない。私が節税の仕組みを調べたり実践したりするのは、税金の仕組みを学ぶために過ぎない。ただ知識として学ぶよりも、実際に実践して運用してみる方が学びになる。

以前の 出張もくもく会 の後で懇親会のときにそのうち資本主義は新しい制度にとって変わられるのではないかという話題があった。それは行き過ぎた資本主義の弊害と、資本主義である限り40時間/週の労働時間から抜け出すには資本家になるしかなくて、人類はすでにこれだけ技術があるのだからもっと多くの人が今よりも働かずに食べていけるのではないかと多くの人が考えている。私の場合も、実質は自分のやりたいことしかやってなくて、自分のために働きながらも、老後のために一応はお金をもらっておくみたいな働き方になっている。この考え方は資本主義の次の制度へ移行するときに活きてくればいいなと思う。