Linux Socket Interfaceではまる

一昨日あたりから、仕事のため、昔Cで書いたSocket Interfaceを用いて通信を行うサーバ・クライアント型アプリケーションのデバッグを行っている。昔、Socketを初めて使って書いたプログラムである。というか、それ以来、プログラムといったらほとんどJava、あとはRubyって感じになっちゃって、Unix Socketなんて使ってないんだけども。
プログラムには何箇所か問題があったんだけど、ほとんどがすぐに解決できるものだった。だけど、1つだけはまった。実行環境によってはサーバ側がクライアントからの要求をacceptすると、acceptに失敗すること。実際、acceptの戻り値が-1になり、errnoは22、perrorで出力するとInvalid Argumentが出てくる。問題のacceptは以下のコード。

client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

何時間もかけて、原因はclient_lenが初期化されていないこと、だってわかったんだけど、情けなかったな。次のようにきちんと初期化されていないとダメ。

client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

まぁ、client_lenは入出力両用の引数だから、初期化されてないとダメなのは当たり前なんだけども。ちなみに、初期化されてなくて変な値が入っているのを確認したのはstraceっていうツール。Linuxシステム開発者にはgdb同様必須のツールのようだ。あと、valgrindでも確認できた。僕はこの3つのツールはどれも使い方を知らなかったし、先輩に教えてもらうまではstraceとvalgrindは存在も知らなかった。でも、この3つが使えれば最低限やっていけそうなので、早く使い方を習得しようと思う。
今回のこのミスは、まぁ、僕がLinux Cプログラミング初心者ってのもあるので、あまり自分を責めないでおこう。なによりも早くツールの使い方をマスターすること。今後、C on Linuxでの開発も増えてくるだろうし。
ちなみに、「実行環境によってはacceptで失敗する」って書いたけど、僕が確認したのは、Debian Sargeを使っているとき。Debian WoodyやFedora Core 4では問題なく実行できた(でも、このことに問題があるんだけどもw)。libcのバージョンは詳しくは調べてないです。Sargeのlibcがglibc 2.3.2.ds1-22sarge3ってことしか調べてないです。