2010년 4월 초에  Tomcat Race Condtion 에 대한 버그 리포트와 Patch가 올라왔습니다. https://issues.apache.org/bugzilla/show_bug.cgi?id=48843

 

이 문제는 리퀘스트가 많이 나타날 수 있는 Critical 버그로서, 동시성 관련된 문제(Race Condition)입니다. AJP 뿐 아니라 NIO, JIO 까지 관련된 문제입니다.

 

문제가 된 코드는 다음과 같습니다.

요청을 받으면 톰캣의 WorkerThread를 하나 얻어오도록 합니다. Worker thread가 없으면 대기하고, 있으면 Worker Thread를 리턴합니다.

(Consumer-Producer의 전형적인 코드입니다. )

 

protected Worker getWorkerThread(){

...

Worker workerThread = createWorkerThread();

        while (workerThread == null) {

            try {

                synchronized (workers) {

                    workers.wait();

                 }

            }

...

}

 

내부 Worker 쓰레드 내용

protected class Worker implements Runnable {

….

private synchronized Socket await() {

// Wait for the Connector to provide a new Socket

         while (!available) {

                 try {

                     wait();

                  } catch (InterruptedException e) {

                  }

          }

 

          // Notify the Connector that we have received this Socke

        Socket socket = this.socket;

          available = false;

          notifyAll();

return (socket);

}

 

 

만약 Request 쓰레드가 2일 때를 가정했을 때 (maxThread=2), Request 쓰레드와 Acceptor 쓰레드간의 Race condition 상황에서 재현될 수 있습니다.

 

1.     Acceptor 쓰레드가 workerThread null인 상태에서 “while 를 통과하였습니다.

2.     요청을 완료한 Request 쓰레드가 recycleWorkerThread()를 실행하고 나서, Worker.await()메소드에서 연결 요청을 받기 위해서 wait() 메소드에서 대기하고 있습니다.

3.     Acceptor 쓰레드가 workers.wait() 메소드에서 무한 대기를 합니다.

 

서로 깨워주지(notify) 못한 채, 연결 요청을 처리해 주지 못하게 됩니다.

 

<수정사항>

AJP, NIO, JIO EndPointer가 수정되었습니다.

 

protected Worker getWorkerThread() {

         // Allocate a new worker thread

-        Worker workerThread = createWorkerThread();

-        while (workerThread == null) {

-            try {

-                synchronized (workers) {

+        synchronized (workers) {

+            Worker workerThread;

+            while ((workerThread = createWorkerThread()) == null) {

+                try {

                     workers.wait();

+                } catch (InterruptedException e) {

+                    // Ignore

                 }

-            } catch (InterruptedException e) {

-                // Ignore

             }

-            workerThread = createWorkerThread();

+            return workerThread;

         }

-        return workerThread;

     }

 

 

<웹 영향도>

추후 최신 버전으로 패치 버전을 받아 업그레이드를 해야 함.

하지만, maxThreads 디폴트가 200 이므로, 아주 Critical 이슈는 없을 것으로 생각됨..

 

 


'Web service' 카테고리의 다른 글

Tomcat Major 패치 (5.5.29, 6.0.27) - 파일 다운로드 관련  (0) 2010.04.12
톰캣 7 개발 도구  (0) 2010.04.12
AJP 연결 테스트 (AJP command line client)  (0) 2010.04.05
Reverse Proxy  (0) 2010.04.05
쓸만한 플래쉬  (0) 2010.03.19
Posted by '김용환'
,