TIME_WAITで待つ時間を短縮とかそういう逃げしかないかと。。
「自分のシステム内の」話か
なら、プロトコル変更するのがベストじゃね
>今作っている少し複雑なプログラムで、記述子がどんどん大きくなっていって、いずれ
>ulimitで設定されて限界に達してしまいます。
問題がここなら、上限値を上げるしかない。
それでだめならシステムとして破たんしているということ。
上限をあげるのはいいのですが、
プロセスが終了しないと、記述子がずっと上がり続けてしまうんです。
(なので、いつかは上限に達してしまう。)
以下のような簡単なプログラムのテストだと、プロセス内で何回socket, connect, closeしても、
closeした後すぐに前使った記述子が使えています。
while (1)
{
int sock = socket(...); // 毎回同じ記述子が使われる
...
connect(...);
...
close(sock);
}
ちゃんとcloseしてないんじゃないの?
straceで調べてみたら
shutdown してなくね?
んー、してるんですがね。。
どっちが先にしろ、両方ともcloseしていれば、いいんですよね?
closeしなければCLOSE_WAITになって今度はbindできなくなる。
>毎回同じ記述子が使われる
それはたまたまそうなっただけw
>>958 全部読んでからcloseするのと、
残してcloseするのでは全然違う。
というかSocket FAQを一度読んだ方がいい。
(システムの他の部分に影響が出る可能性があるので)
最後の手段だと思うが、
TIME_WAITの時間はほとんどのOSで変更可能。
逆に、上の単純なプログラムで、なんでTIME_WAITが起きないかも謎です。
クライアントも同じ記述子番号がsocketで返ってくるし、サーバもacceptしたソケットが
毎回同じ記述子番号です。
>プロセスが終了しないと、記述子がずっと上がり続けてしまうんです。
明らかにクローズしてない。ふつうは互いにFINを受け取るとディスクリプタは解放されるもん。
forkした後クローズしてないで終わってるところがあったりしてないか?
子プロセスはディスクリプタも引き継ぐが、クローズしないでプロセス終了してもソケットはつかんだまま昇天するから要注意だ。
ディスクリプタが同じなのはたまたまだよ。
別のシステムで取り会いになるのが普通だから。
ディスクリプタが同じなのかどうかは問題ではない。
closeはちゃんとしてると思います。コード的にも。
netstat -an|awk '/tcp/ {print $6}'|sort|uniq -c
なコマンドでstatusの数を見てますが、
netstatで見ても、TIME_WAITがどんどん増えていきます。(それ以外は変わらず)
なので、結果的にもちゃんとクローズされているのかと思っています。
定期的にsocket, connect, closeを繰り返すクライアントのプログラムを一旦、
Ctrl-Zで止めると、次第にTIME_WAITが減っていきます。(期待通り)
しかし、プロセスをfgで再開しても、socket(2)で開いていく記述子番号は止めたところから、
さらに増えていきます。
forkした後クローズしてないで終わってるところがあったりしてないか?
子プロセスはディスクリプタも引き継ぐが、クローズしないでプロセス終了してもソケットはつかんだまま昇天するから要注意だ。
forkはそもそもしていないです。サーバ側はマルチスレッドのサーバで、各スレッドは
同じソケットに対してacceptをしています。
クローズはちゃんと出来てるんでしょ?漏れもそう思うよ。
だって中断したらTIME_WAITが減っていくわけだからね。
で、ディスクリプタの値がドンドン増えていくのと、同じ値が使われるのの違いが知りたいんでしょ?
単にそういうアルゴリズムなんじゃないの?
たとえば上のド単純なサンプルの場合、sendとかしてなくて、それが理由でソケットディスクリプタの数値が再利用されてるとかさ。
その辺は実装依存だろ。知ってる人がいるかも知れないけどね。
ソースが出てこない以上はそんな実装依存の部分の動作までわかんないよ。
ディスクリプタの値が増えようが増えまいが単にソケットの上限に達してるという結論は変わるまい。
上限を増やすか設計を見直すか、本当にforkが無いのかよっくチェックするかしか無いでしょ。
単純なサンプルでも一応send,recvしてます。上のやつでは省略しただけでした。
ディスクリプタの値が増えようが増えまいが構わないですが、一方(増える方だけ)
上限に達します。なので、小さい番号が使えないので、大きい番号を選択してるという
挙動に見えます。
じゃあ、ソケット上限に達したときに一時中断させてしばらくまってから再開したらどうよ。
それでも再開直後からソケット生成でコケるなら本当に誰かがつかみっぱなしなんじゃないの?
上限手前で中断して、再開してもソケット生成に失敗しますね。
プロセスを一旦止めれば、また小さい番号の記述子から始まります。
closeはされているが、プロセスがsocketを解放しないということってありますか?
so_reuseaddrセットしてみるとか
三回は言わない。
>>961 > 全部読んでからcloseするのと、
> 残してcloseするのでは全然違う。
理解できてる?
shutdownとcloseの違いは理解している?
> というかSocket FAQを一度読んだ方がいい。
読んだ?
>> 全部読んでからcloseするのと、
>> 残してcloseするのでは全然違う。
>理解できてる?
>shutdownとcloseの違いは理解している?
理解しているつもりです。
>> というかSocket FAQを一度読んだ方がいい。
>読んだ?
読みました。書き込みが終了したらshutdown(s, 2) して、EOFを受信するのをまって、closeしています。
>974
どのような状況で起きますでしょうか?
恐慌は人の心によって引き起こされる
問題解決しました。
使っていたライブラリ(libevent)の使い方が間違っていたのが原因でした。
リクエストの度に毎回event_init()をしていました。。。
その後、ファイルディスクリプタをaddしていて、libevent内部でそのディスクリプタを
つかみっぱなしのままという感じでしょうか。
なので、コネクションはcloseされていても、ファイルディスクリプタが解放されないという
変な現象が起きていました。
色々相談に乗って頂いた方、ありがとうございました。
結果的に私のしょぼすぎるミスでしたが、とても勉強になりました。
よかったよかった
ここはおまいの日記です
絶対自分のミスを疑わない香具師っているよな
かれこれ70レス消費したのか
919の人気に嫉妬
それじゃクローズされてないし…
close==ファイルディスクリプタの解放だからPOSIXでは。
livevent使ってたんかいw
先にそれを家w
まぁ
よかったぉ
クローズしてたと思ったけど、
ファイルディスクリプタ管理に失敗していたわけですね。
close(2)の帰り値はチェックしてないと。
liveventって何?
俺はこういう流れ好きだぜ?
あーだこーだ言ったりして色々勉強になるし
パズルみたいで。
最初はすごい不思議な話なのが、最後にすっきり解決って楽しい。
バグって面白くね?(他人のを見ているぶんには)
>>977 のファイルディスクリプタをつかみっ放しって
意味わからない。dupしてるとか?
だからstraceしれって言ったのに
>>988 いや、クローズに失敗していただけ。
event_initして管理テーブル飛ばしてたから。
straceもいいけど、エラーチェックぐらいしようよ
992 :
デフォルトの名無しさん:2008/12/28(日) 21:02:52
きみらなんでそんなにひまなの?
しぬの?
gj
乙py
うめ
997 :
デフォルトの名無しさん:2008/12/28(日) 21:51:40
来年はスーパーインフレ
1000 :
デフォルトの名無しさん:2008/12/28(日) 21:53:31
1001 :
1001:
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。