Article delegate-ja/53 of [1-251] on the server localhost:7119
  upper oldest olders older1 this newer1 newers latest
search
[Top/Up] [oldest] - [Older+chunk] - [Newer+chunk] - [newest + Check]
[Reference:<_A52@delegate-ja.ML_>]
Newsgroups: mail-lists.delegate-ja

[DeleGate-Ja] Re: HTTP Proxyでページが途中までしか読み込まれない(EMERGENCY EXIT)
22 May 2007 00:55:24 GMT ysato@delegate.org (Yutaka Sato)
The DeleGate Project

In message <_A52@delegate-ja.ML_> on 05/21/07(22:43:44)
you Katsuaki Shimadera <pe4aabrv6-mxhgu4ycrwxw.ml@delegate.org> wrote:
 |Solaris 10 x86上でHTTP Proxyを構築しています。
 |delegateのバージョンを9.5.6から9.6.0に上げたところ、一部のWebサイトで
 |ページが途中までしか読み込まれないという現象が発生するようになりました。
 |
 |再現する条件として、CACHEが有効になっているときに発生することがわかりま
 |した。

詳細なレポートありがとうございます。これは、Solarisに固有の問題のようです。

・キャッシュを有効にするとDeleGateは gunzip/gzip を実行する
  server → recvbodyスレッド → gunzipスレッド → DeleGate → gzip → client
                         +キャッシュ
・9.6.0ではgunzipがDeleGateとpipeで接続されたスレッドで実装されている
・gunzipからの最初の出力をなるべく速やかにクラアイントに中継しようと
 gunzipスレッドでの gzopen()時に、入力pipeをnon-blocking状態にしている
・SunOSではこのnon-blocking状態での、Zlib中での freadが何らかの副作用を
 残すらしい (おそらくFILEのEOFが設定される)
・このためgunzipスレッドが最初に読み込んだぶんだけ中継して即終了してしまう
・DeleGate(recvHTTPbody)はさらにつづきの部分をgunzip向けのpipeに書き込もうと
 するが errno == EPIPE (+SIGPIPE) で失敗する
・クライアントに送られるデータが尻切れになる

というようなことだと思われます。


 |条件1のログ(log_9.6.0_cache-do/8080)の254行目に、以下のようなエラーが出
 |ておりここで通信が切れているように思います。
 |
 |  #### EMERGENCY EXIT (disk full in recvHTTPbody?)
 |
 |disk fullのエラーとなっていますがHDDの空きは30GB程度ありdelegatedの実効
 |ユーザで書き込みもできます。

この部分は9.6.0より前は、pipeではなくファイルへの出力となっていたため、
書き込みエラー即ディスクfullというメッセージを出していた名残です。
実際には、パイプへの書き込みエラーですね。


 |同じ条件で9.5.6では正常にアクセスできました(条件3)。

9.5.6 では上記のようなパイプラインではなく、データを一旦すべて一時ファイル
に受け取ってから、gunzip するようになっていますので、この問題は起こりません。


 |コンパイル済みのバイナリ(sol10i-dg)も試しましたが同じ現象が発生しました。
 |しかし、Windows版では現象は発生しないようでしたのでSolaris版特有かもしれ
 |ません。

各種のLinuxや、FreeBSD、MacOSXで調べましたが、問題が起こるのはSolaris
(SunOS5.5, 5.10)だけでした。
最終的な対処は、Zlib内の動作を調べてからになりますが、とりあえずSolaris
では、同封のパッチのように、上記の non-blocking I/O を無効にすることで、
この問題を回避できると思います。

もしこれがSoliarsの、non-blocking 状態での fread() の実装の問題(バグ)で
あるなら、これが実際の対処方法になります。これによって、非常に低速な回線
でのgzipの中継に問題(最初のデータが受信できるまでの待ち時間が長くなる)が
生じますが、ほとんどの場合、実用上の影響はありません。

なおこれは、もともとZlibのgzio.c:gzopen(),gzread()の実装の問題(常に受信
バッファをいっぱいにしてから処理しようとするので、ストリーム型の処理に向か
ない)をとりあえず回避しようとしたものでもあります。gzio.cにはこの他にも
手を入れたいところがありますので、根本的な解決のためには、gzio.c 相当の
ものを自前で作らないといけないと思っています。

                   9 9  
┌─┐┬┌──┬┐ //\^^ ( e ); {Do the more with the less -- B. Fuller}
├─┤│└─┐│ / 877m\_<   >_ <URL:http://www.delegate.org/delegate/>
┴ └┴──┘┴──────────────────────────────
佐藤豊@情報技術研究部門.産業技術総合研究所(独立行政法人)

*** ../delegate9.6.0/filters/gzip.c	Wed Apr  4 03:09:31 2007
--- filters/gzip.c	Tue May 22 09:16:42 2007
***************
*** 444,451 ****
--- 444,453 ----
  	 * apply NBIO to gzopen() which will do fread() at the start.
  	 * applying NBIO also to gzread() seems to break the gzip.
  	 */
+ #if !defined(sun)
  	setNonblockingIO(fileno(in),1);
  	nonblock = 1;
+ #endif
  	ready = fPollIn(in,10*1000);
  	if( ready == 0 ){
  fprintf(stderr,"----[%d] gunzipFilter: ready[%d]=%d\n",

  admin search upper oldest olders older1 this newer1 newers latest
[Top/Up] [oldest] - [Older+chunk] - [Newer+chunk] - [newest + Check]
@_@V