この辺、投稿としてまとめておく。
内容がダブってしまうが、事前に考えていないということだな。
内容がダブってしまうが、事前に考えていないということだな。
(1) KeepAlive接続の場合
接続済みのソケットにKeep-Aliveでリクエストが届くと、そのときに空きworkerスレッドが獲得できなければ、ソケットはクローズされる
(httpd-2.4.7/server/mpm/event/event.c) 1368 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy) 1369 { : 1414 for (;;) { : 1495 while (num) { 1496 pt = (listener_poll_type *) out_pfd->client_data; 1497 if (pt->type == PT_CSD) { 1498 /* one of the sockets is readable */ : 1502 switch (cs->pub.state) { 1503 case CONN_STATE_CHECK_REQUEST_LINE_READABLE: 1504 cs->pub.state = CONN_STATE_READ_REQUEST_LINE; 1505 remove_from_q = &keepalive_q; 1506 /* don't wait for a worker for a keepalive request */ 1507 blocking = 0; 1508 /* FALL THROUGH */ 1509 case CONN_STATE_WRITE_COMPLETION: 1510 get_worker(&have_idle_worker, blocking, 1511 &workers_were_busy); : 1532 /* If we didn't get a worker immediately for a keep-alive 1533 * request, we close the connection, so that the client can 1534 * re-connect to a different process. 1535 */ 1536 if (!have_idle_worker) { 1537 start_lingering_close_nonblocking(cs); 1538 break; 1539 } :
1510行目のget_worker()で利用可能なworkerスレッドが得られない場合(have_idle_workerが0)に、
1537行目でソケットを閉じている。
1532行目のコメントにもあるように、keep-aliveなリクエストに対してworkerスレッドが確保できなければ、直ちに接続を切り、クライアント側が再接続するのを待つという仕様になっている。
(2) 新規接続の場合
この場合、accept可能になった時点で、空きworkerスレッドが確保できなければ、accept自体を行わない。
(httpd-2.4.7/server/mpm/event/event.c) 1615 get_worker(&have_idle_worker, 1, &workers_were_busy); 1616 rc = lr->accept_func(&csd, lr, ptrans);
1615行目で、get_worker()は空きworkerスレッドが獲得できるまでブロックする。
そして、獲得後に、1616行目の関数からaccept()が実行される。
もし、別の子プロセスがいて、空きworkerスレッドがいたなら、そちらが先にaccept することになる。
この場合、空きworkerスレッドを待っていた子プロセスで、空きworkerスレッドが確保できて、1615行目から抜けたときの処理は、event MPMではソケットが非ブロックになっているので、1616行目の関数から呼び出されるaccept()処理が失敗する。
その後、確保したプールを解放するなどの処理を行ってから、何事もなく listenerスレッドとして監視処理を継続することになる。