2014年8月28日木曜日

リクエスト処理の流れ: ap_process_request_after_handler

ap_process_async_request()関数の最後に実行されている幾つかの関数を見ておく。
(リクエストの処理の流れ)
書き散らかしているだけで、分かりやすくはできていないのだが、一通り見ておきたい。

(httpd-2.4.9/modules/http/http_request.c)

272 void ap_process_async_request(request_rec *r)

273 {
  :

ここまでのリクエストの処理結果がOKかそうでないかで分岐している。

345     if (access_status == OK) {
346         ap_finalize_request_protocol(r);
347     }
348     else {
349         r->status = HTTP_OK;
350         ap_die(access_status, r);
351     }
352
353     ap_process_request_after_handler(r);
354 }

(6)ap_finalize_request_protocol

レスポンスの送信完了時に呼び出される。
この唯一の目的は、(transfer-encodingのような)レスポンスボディまわりのラッパーに対してプロトコル終了情報を通知することだ、とコメントにある。

(httpd-2.4.9/server/protocol.c)

1228 /* finalize_request_protocol is called at completion of sending the
1229  * response.  Its sole purpose is to send the terminating protocol
1230  * information for any wrappers around the response message body
1231  * (i.e., transfer encodings).  It should have been named finalize_response.
1232  */
1233 AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
1234 {
1235     (void) ap_discard_request_body(r);

ap_discard_request_body()はリクエストボディを読み込む(読み捨てる)。
通常、既に読み込んでいるはずだ。

1236
1237     /* tell the filter chain there is no more content coming */
1238     if (!r->eos_sent) {
1239         end_output_stream(r);

end_output_stream()では、bucket brigadeを作成、
EOSメタデータバケットを作成し、bucket brigadeの末尾に追加する。
bucket brigadeをrequest_recのoutput_filtersに引き渡す処理が行われる。
出力フィルタでは、EOSメタデータバケットを受け取ると各種の終了処理が行われる。
CHUNK出力フィルタ(データをchunkedエンコーディングするフィルタ)では確かに、終了を示すchunkを作成している。

1240     }
1241 }

(7)ap_die

ap_die関数は、エラーレスポンスを返す。
ErrorDocumentの指定にも対応する。
ここでは取り上げない。

(8)ap_process_request_after_handler

ここはこれまで何度か名前を出した EOR メタデータバケットの追加処理が行われている。
つまり、リクエスト処理の終了を準備していることになる。

242 AP_DECLARE(void) ap_process_request_after_handler(request_rec *r)

243 {
244     apr_bucket_brigade *bb;
245     apr_bucket *b;
246     conn_rec *c = r->connection;
247
248     /* Send an EOR bucket through the output filter chain.  When
249      * this bucket is destroyed, the request will be logged and
250      * its pool will be freed
251      */

EORメタデータバケットを作成し、出力フィルタチェーンに引き渡す。
EORバケットが破棄されるタイミングで、アクセスログへの出力が実行され、requestメモリプールが解放される。

252     bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);

bucket brigade bbを作成

253     b = ap_bucket_eor_create(r->connection->bucket_alloc, r);

EORメタデータバケットを作成

254     APR_BRIGADE_INSERT_HEAD(bb, b);

EORメタデータバケットを brigadeの先頭に挿入。
この時点ではbucket brigade bbにはEORバケットだけが含まれている。

255
256     ap_pass_brigade(r->connection->output_filters, bb);

その bucket brigade bb を出力フィルタに引き渡す。
この出力フィルタは、r->output_filtersではなく、conn_recに登録されている出力フィルタに直接、引き渡す。
コネクションフィルタによる処理だけ行うということだ。
プロトコルフィルタ以上の階層(request_recに登録されている階層)の処理は終わっているということだろう。
ただし、この処理タイミングでEORバケットが破棄されている(処理されている)とは限らない。

257
258     /* From here onward, it is no longer safe to reference r
259      * or r->pool, because r->pool may have been destroyed
260      * already by the EOR bucket's cleanup function.
261      */

EORバケットが処理済みであれば、requestメモリプールが解放されているため、
request_rec情報は無効になっている。
request_rec情報 *rは使ってはいけないことになる。

262
263     if (c->cs)
264         c->cs->state = CONN_STATE_WRITE_COMPLETION;

ここで、コネクションの状態情報がCONN_STATE_WRITE_COMPLETIONにセットされる。

265     check_pipeline(c);

処理待ちの読み込みデータがないかを確認している。
読込可能なデータがあった場合、conn_rec情報 *cのdata_in_input_filters変数に1がセットされる。

266     AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, r->status);

DTrace関連のマクロと考えているが、詳細はよく分からない。

267     if (ap_extended_status) {
268         ap_time_process_request(c->sbh, STOP_PREQUEST);
269     }
270 }


ここまで。

0 件のコメント:

コメントを投稿