68user's page 掲示板

Prev< No. 2113〜2118> Next  [最新発言に戻る] [過去ログ一覧]
No. 2113 # スナフキン 2001/08/28 (火) 03:14:24
ふと思ったのですが、CGIへPOSTメソッドでデータを送信した時に
そのCGIでデータを受け無い時(readしない場合)って、そのデータは
どうなるのでしょう?

CGIで、最近流行りのバッファーオーバーフロー対策?として、POST
データサイズを予め調べてから、read で読み込むようにしようと
考えましたが、このような場合は、サーバーOS/ソフト側でバッファ
に一旦溜まるのでしょうか?
それとも、CGIが受け取らない限りOS/ソフト側でデータそのものを
受け取らないのでしょうか?

試しに自環境にあるApacheに、アップロード機能付きの掲示板CGIを
使って約80Mbを送信してみましたが、cgi-lib.pl のエラー?でCGIは
停止したらしく、ps コマンドを見ると、zonbi となっていたため、
httpdがタイムアウト処理?をして切断された結果(だと思う)、ブラウザに
「cgi-lib.pl: Request to receive toomuch data: 84400432 bytes」と
表示され切断されたように見えました。
そして、その状態まで送信は止まらずにブラウザは送信を続けていました。

top や free で送信中のメモリの状態を観察していても変化がなかった
事から、CGIが受け取らないと捨てられてしまうようにも見えますが、
ちゃんと試験が出来ていたのか、自信が無いので正確な所は不明です。

結局、CGIでPOSTデータを受け取らなくても(プロセスが死んでいた為)
ブラウザ自身は送信を続けていたので、どの時点で(OSかApache)データ
を破棄しているのかは判断できませんでした。

そもそもCGI側でオーバーフローを気にしなくても良いならば、それでいい
のですが、どうも動作が判りません。
#それとも実装依存なのかな?

No. 2114 # 68user 2001/08/28 (火) 06:58:35
>>2110 /tk
> 余計なような足りないような…
確かに。補足どうもです。

>>2112 moz
> 質問するかもしれませんので、そのときは、どうか
> よろしくお願いします。
ぜひ回答する側にもまわって下さい :-)

>>2113 スナフキン
> そのCGIでデータを受け無い時(readしない場合)って、そのデータは
> どうなるのでしょう?
実装依存です。TCP 的に言えば、相手側がプロセスが read してくれないと相
手側の OS のバッファにたまります。それがいっぱいになったら書き込み側が
ブロックします。つまり
    print SOCKET "....";
を実行したままずっと止まってしまうということです。

ちゃんと調べたわけではありませんが、一般的にPOST データを全部受け取っ
て CGI に渡す web サーバが 多いような印象を受けます。あくまで印象なの
で、試したわけではありません。

もし
    int sock;
    bind(...);
    listen(...);
    sock = accept(...);
    ... ヘッダ読み込み ...

    if ( fork() == 0 ){
        char *args[]={"/home/user/public_html/cgi-bin/foo.cgi", NULL};
        dup2(sock, 0);
        execvp("cgi", args);
    } else {
        int status;
        wait(&status);
    }
のように、直接ソケットを CGI プロセスの標準入力に渡すような
実装ならば、CGI プロセスが read しないと書き込み側がブロック
するわけですね。

apache の実装がどうなっているかわかったら僕にも教えて下さい。

No. 2115 # 68user 2001/08/28 (火) 07:19:15
>>2114 68user
なんかいろいろとアレなので、書き直し。
    int sock;
    int pipes[2];

    bind(...);
    listen(...);
    sock = accept(...);
    ... ヘッダ読み込み ...

    pipe(pipes);

    if ( fork() == 0 ){
            char *args[]={"cgi", NULL};
            dup2(sock, 0);
            dup2(pipes[1], 1);
            execvp("/home/user/public_html/cgi-bin/foo.cgi", args);
    } else {
            char buf[256];
            int len;
            int status;
            while ( len=read(pipes[0], buf, sizeof(buf) ){
                  write(sock, buf, len);
            }
            wait(&status);
    }
ソケットのデータを CGI プロセスの標準入力に渡し、
CGI プロセスの標準出力を受け取り、そのままブラウザに
返す web サーバもどきです。

No. 2116 # CCIE [E-mail] 2001/08/29 (水) 12:43:34
こんにちは。又お邪魔させてもらいました(^^;)
この前はありがとうございます。うまくできました\(^o^)/
今回は、Perl/Tkなんですがアドバイスよろしくお願いします。m(__)m
リストはこんな感じなんですが・・・
use Tk;

$mw = MainWindow->new;
$mw->title("gifgraph");

$can = $mw->Canvas(-width=400,

No. 2117 # CCIE [E-mail] 2001/08/29 (水) 12:52:25
すみません↓ tabで形をそろえようとしたら送信のところにいっちゃってenterおしちゃいました(^^;; ヒヤアセ
で、リストは
use Tk;

$mw = MainWindow->new;
$mw->title("gifgraph");

$can = $mw->Canvas(-width=>400,
                                      -height=>300)
        -pack();

for(;;){
$gif = $mw->Photo(-format=>'gif',
                                    -file=>"graph.gif");

$can->createImage(200,150,-image=>$gif);

$mw->after(4000);
}

画像が更新されるのでfor文で何度も画像を読みこませたいんですが、ウィジェットすら開かないんです。for文をはずせば今ある画像が表示されるんですが、なぜなんでしょうか?

No. 2118 # 68user 2001/08/29 (水) 16:35:02
>>2117 CCIE
Perl/Tk は久しくやってないので忘れてしまいましたが、
    $can->createImage(200,150,-image=>$gif);
    $mw->after(4000, \&change_image);
    MailLoop;
    exit;

    sub change_image {
          $gif が変わっていたら $can をいじる
    }
じゃないですかね。

Prev< No. 2113〜2118> Next  [最新発言に戻る] [過去ログ一覧]