worker MPMでは、listenしているサーバ用のソケットを監視して、クライアントからの接続を受け付け通信用のソケットを用意し、これをworkerスレッドにスレッド間通信用のキューを介して引き渡していた。
これが、event MPMでは、そのほかにも、クライアントからのFIN待ちや、Keep-Alive接続における、次のリクエストの受信待ち等の監視も行うようになっている。
(14) listener_thread
(httpd-2.4.9/server/mpm/event/event.c) 1368 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy) 1369 {
init_pollset()関数では、Listenディレクティブで設定されているサーバソケットでlistener_poll_type情報を作成する。
初期設定では、このListenソケットはすべてlistenerスレッドでのイベント監視対象。
1399 rc = init_pollset(tpool);
1400 if (rc != APR_SUCCESS) {
1401 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1402 "failed to initialize pollset, "
1403 "attempting to shutdown process gracefully");
1404 signal_threads(ST_GRACEFUL);
1405 return NULL;
1406 }
引き続き主ループに進む。
今回はここを見ていく。
長い関数なので、投稿を分けたい。
(1)メインループの開始(本投稿)
(14.1) 主ループ
1414 for (;;) {
1415 int workers_were_busy = 0;
workers_were_busyは、この子プロセスのworkerスレッドに処理可能な空きがあるかどうかのフラグだ。
0は空きがある(ビジーではない)。
get_worker()関数でセットされる。
get_worker()関数は、workerスレッドの空き(アイドルスレッド)の有無をチェックする。
これは2つのモードで動作する。
- 空きがない場合に、空きができるまでブロックするのがブロックモード(第2引数が1)
- 空きがなければ、APR_EAGAINで直ちに返ってくるのが非ブロックモード(第2引数が0)
このlistenerスレッド関数ではいずれのモードも利用されている。
そして、get_worker()で第3引数に与えられている workers_were_busy は以下のケースで1がセットされる。
- ブロックモードで、アイドルworkerスレッドがなく空き待ちを実行した場合
(ブロックモードの場合、アイドルworkerスレッドがなく空き待ちを実行すると、正常な状態なら実際にアイドルworkerスレッドが得られてからreturnする) - 非ブロックモードでアイドルworkerスレッドがなく、直ちにAPR_EAGAINで返った場合
1416 if (listener_may_exit) {
listener_may_exit はプロセスの終了フラグ。
このフラグが立っている場合、listenerスレッドは終了処理を始める。
このif文は終了処理だ。
とりあえず、今回はリクエスト処理の流れを追いたいので見ない。
1417 close_listeners(process_slot, &closed);
1418 if (terminate_mode == ST_UNGRACEFUL
1419 || apr_atomic_read32(&connection_count) == 0)
1420 break;
1421 }
1422
1423 if (conns_this_child <= 0)
conns_this_childは、MaxConnectionsPerChildのチェック用の変数だ。
初期値にMaxConnectionsPerChildをセットし、接続を受け付けるごとにカウントダウンする(1630行目)。
値が0以下だと、処理数がMaxConnectionsPerChildを越えたことになる。
以下の関数check_infinite_requests()では、MaxConnectionsPerChildに0以外の値が指定されていた場合に、停止処理を実行している。
(MaxConnectionsPerChildが0の場合は無制限にリクエストを処理できる)
1424 check_infinite_requests(); 1425 1426 now = apr_time_now();
現在時刻を変数nowにセット。
1427 if (APLOGtrace6(ap_server_conf)) {
このif文はTRACEログの出力が有効な場合に実行される。
LogLevel mpm_event:trace6
と指定してやると、この条件に入る(省略)。
1443 } 1444
以下ではスキップリストのチェックを行っている。
スキップリストはタイムアウト処理を管理している。
これは apr_skiplist とmod_dialupモジュールで簡単には見ている。
スキップリストをチェックして、次のタイムアウト処理までの時間を確認する。
1445 apr_thread_mutex_lock(g_timer_skiplist_mtx); 1446 te = apr_skiplist_peek(timer_skiplist); 1447 if (te) { 1448 if (te->when > now) { 1449 timeout_interval = te->when - now; 1450 } 1451 else { 1452 timeout_interval = 1; 1453 } 1454 } 1455 else { 1456 timeout_interval = apr_time_from_msec(100); 1457 } 1458 apr_thread_mutex_unlock(g_timer_skiplist_mtx); 1459
timeout_interval 変数に、その時間をセットする。
既に指定のタイムアウト時刻を過ぎていた場合には、1をセットしている。
タイムアウトイベントがなければ、100ミリ秒がセットされる。
続いて、イベントチェック処理に進む。
0 件のコメント:
コメントを投稿