· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Apache 2.0 Thread Safety Issues


Copyright 2006 The Apache Software Foundation. Licensed under the [http]Apache License, Version 2.0

Korean Translator: 김정균 <http://oops.org>

번역본 참고 사항

  • 이 문서의 번역 결과물로 인하여 발생하는 문제에 대하여 책임을 지지 않습니다.
  • 이 문서의 번역물은 원문의 저작권에 의거하여 수정 배포될 수 있습니다.
  • 이 문서의 원본은 http://httpd.apache.org/docs/2.2/developer/thread_safety.html 입니다.
  • 짧은 프로그래밍 지식으로 번역을 하였기 때문에 오역이 있을 수 있습니다.


Apache 2.0 에서 어떤 쓰레드 mpm 을 사용할 경우, Apache 에서 호출되는 모든 함수가 thread safe 해야 하는 것은 상당히 중요한 일입니다. 3th party extension 이 링크(link)되었을 경우, 서버가 thread safe 한 결과를 가진다고 말하기는 힘이 듭니다. 이 문제는 과중한 로드가 걸려야 하고, 어떤 상태에서 나타날지 모르는 미묘한 race condition 과 같이 발생하기 때문에, 일반적으로 일시적인 테스트로는 thread safe 하다고 말할 수는 없습니다.

1. 전역 변수와 정적 변수


모듈을 작성하려고 하거나, 모듈 또는 3rd party 라이브러리가 thread safe 하다고 결정을 하려 할 때, 유의할 일들이 있습니다.

먼저, 각 개별 thread 가 자신만의 프로그램 counter, stack, register 를 가지고 있는 thread 모델인지 확인할 필요가 있습니다. 로컬 변수들은 stack 에 저장이 되기 때문에 문제가 없습니다. 하지만, 어떤 정적 변수나 전역 변수는 주의해야할 필요가 있습니다. 이는 절대적으로 정적 또는 전역 변수를 사용하지 말아야 한다는 것은 아닙니다. 어떤 변수가 모든 thread 에 영향을 미치기를 원하는 경우가 있을 수 있습니다. 하지만 일반적으로 당신의 코드가 thread safe 하기를 바란다면, 이 변수를 정적/전역 변수로 사용하는 것을 피하는 것이 좋습니다.

프로그램 전체와 모든 thrad 에서 접근을 할 필요가 있는 전역 변수가 있을 경우, 이 변수를 업데이트 함에 있어 대단히 주의해야 합니다. 예를 들어, counter 를 증가 시키는 변수라면, 다른 thread 에 race condition 을 피하기 위하여 최소한으로(atomically) 증가를 시켜야 할 수도 있습니다. 당신은 mutex (mutual exclustion)를 이용하여 이것을 할 수 있습니다. mutex 에 락을 걸고, 현재 값을 읽고, 그 변수를 증가 시킨 후에 쓰고, mutex 의 락을 해제 하십시오. 값을 변경하기를 원하는 다른 어떤 thread 는 변수가 클리어 될 때까지 먼저 mutex 를 검사하고 블럭 시켜야 합니다.

만약 APR을 사용하고 있다면, apr_atomic_* 함수와 apr_thread_mutex_* 함수를 참조 하십시오.

2. errno


errno 는 마지막으로 발생한 에러의 에러 번호를 가지고 있는 전역 변수 입니다. 하나의 쓰레드가 errno 를 설정하는 low-level 함수를 호출하였고, 다른 쓰레드가 이 변수를 참조 하였을 경우, 참조한 쓰레드로 원치않는 errno 를 전달하게 됩니다. 이 문제를 해결하기 위하여, 모듈과 라이브러리에 _REENTRANT 상수를 선언하거나 또는 컴파일 시에 -D_REENTRANT 옵션을 주실 수 있습니다. 이 상수는 errno 를 per-thread 변수로 만들어 주며, 코드를 투명하게 할 수 있습니다. 이 상수를 선언하는 것은 다음과 같이 작동을 하도록 합니다:

#define errno (*(__errno_location()))

이 코드의 의미는 errono 에 접근을 하면, libc 에서 제공되는 __errno_location() 이 호출이 됩니다. _REENTRANT 를 설정하면, 동등한 기능을 가진 *_r 함수를 제공할 경우 강제로 이 함수들로 재정의 합니다. 그리고 가끔 안전한 함수 호출을 위해 getc/pubc 매크로를 변경하기도 합니다. _REENTRANT 를 추가하는 것 외에 이 문제에 대하여 영향을 미칠수 있는 심볼로는 _POSIX_C_SOURCE, _THREAD_SAFE, _SVID_SOURCE, _BSD_SOURCE 등이 있습니다. 이 것에 대해서는 libc 문서를 참조 하십시오.

3. Common standard troublesome functions


thread safe 하게 만들어야 할 뿐 아니라 재진입(?..reentrant)이 가능 해야만 합니다. strtok 가 명확하게 이 문제를 가지고 있습니다. strtok 가 기억을 하고 있는 구분자로 strtok 를 처음 호출을 하고, 각각의 수반되는 호출에 다음 토큰을 반환하게 됩니다. (의미를 잘 모르겠군요..You call it the first time with your delimiter which it then remembers and on each subsequent call it returns the next token.) tokenizing 상태를 관리하기 위하여 함수가 자신의 정적 스토리지 대신에 사용하기 위하여 할당된 char * 를 포함한 특별한 인자를 가진 strtok_r() 이라고 불리는 재진입 버전의 함수를 가지고 있습니다. APR 을 사용한다면, apr_strtok() 를 사용할 수 있습니다.

crypt() 역시 재진입(reentrant)이 되지 않는 함수 중의 하나 입니다. 그러므로 라이브러리에 있는 이 함수를 가로질러서 호출하는 것은 피해야 합니다. 어떤 시스템에서는 재진입이 가능하기 때문에, 항상 문제가 되는 것은 아닙니다. If your system has crypt_r() chances are you should be using that, or if possible simply avoid the whole mess by using md5 instead.


4. Common 3rd Party Libraries


다음은 Apache 의 3th party 모듈이 사용하고 있는 system 라이브러리의 리스트 입니다. 당신이 상용하는 모듈이 잠재거으로 안전하지 않은 라이브러리를 사용하고 있다면, ldd(1) 나 nm(1) 과 같은 도구를 사용하여 확인을 할 수 있습니다. 다음의 예는 PHP 를 이용하여 확인하는 것입니다:

% ldd libphp4.so
libsablot.so.0 => /usr/local/lib/libsablot.so.0 (0x401f6000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x402da000)
libsnmp.so.0 => /usr/lib/libsnmp.so.0 (0x402f9000)
libpdf.so.1 => /usr/local/lib/libpdf.so.1 (0x40353000)
libz.so.1 => /usr/lib/libz.so.1 (0x403e2000)
libpng.so.2 => /usr/lib/libpng.so.2 (0x403f0000)
libmysqlclient.so.11 => /usr/lib/libmysqlclient.so.11 (0x40411000)
libming.so => /usr/lib/libming.so (0x40449000)
libm.so.6 => /lib/libm.so.6 (0x40487000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x404a8000)
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x404e7000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x40505000)
libssl.so.2 => /lib/libssl.so.2 (0x40532000)
libcrypto.so.2 => /lib/libcrypto.so.2 (0x40560000)
libresolv.so.2 => /lib/libresolv.so.2 (0x40624000)
libdl.so.2 => /lib/libdl.so.2 (0x40634000)
libnsl.so.1 => /lib/libnsl.so.1 (0x40637000)
libc.so.6 => /lib/libc.so.6 (0x4064b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)

게다가, 이 라이브러리들 외에도 모듈에 정적으로 링크된 라이브러리가 있다면 이것 역시 확인해 보아야 합니다. 각 모듈의 개별 심볼을 보기 위해서는 nm(1)을 사용할 수 있습니다.

5. Library List


이 리스트에 추가하여야 하거나 수정해야 할 사항이 있다면 dev@httpd.apache.org 로 연락을 주십시오.


라이브러리 버전 Thread Safe? 비고
ASpell/PSpell ?
Berkeley DB 3.x, 4.x Yes Thread 간의 공유 연결(sharing conenction)에 대하여 주의해야 함.
bzip2 Yes low-level, high-level API 모두 thread safe 함. 하지만, high-level API 를 사용함에 있어 errno 에 접근을 할 때 thread safe 하도록 사용해야 함.
cdb ?
C-Client Perhaps c-client uses strtok() and gethostbyname() which are not thread-safe on most C library implementations. c-client's static data is meant to be shared across threads. If strtok() and gethostbyname() are thread-safe on your OS, c-client may be thread-safe.
cpdflib ?
libcrypt ?
Expat Yes Need a separate parser instance per thread
FreeTDS ?
FreeType ?
GD 1.8.x ?
GD 2.0.x ?
gdbm No Errors returned via a static gdbm_error variable
ImageMagick 5.2.2 Yes ImageMagick docs claim it is thread safe since version 5.2.2 (see Change log).
Imlib2 ?
libjpeg v6b ?
libmysqlclient Yes Use mysqlclient_r library variant to ensure thread-safety. For more information, please read http://www.mysql.com/doc/en/Threaded_clients.html.
Ming 0.2a ?
Net-SNMP 5.0.x ?
OpenLDAP 2.1.x Yes Use ldap_r library variant to ensure thread-safety.
OpenSSL 0.9.6g Yes Requires proper usage of CRYPTO_num_locks, CRYPTO_set_locking_callback, CRYPTO_set_id_callback
liboci8 (Oracle 8+) 8.x,9.x ?
pdflib 5.0.x Yes PDFLib docs claim it is thread safe; changes.txt indicates it has been partially thread-safe since V1.91: http://www.pdflib.com/products/pdflib/index.html.
libpng 1.0.x ?
libpng 1.2.x ?
libpq (PostgreSQL) 7.x Yes Don't share connections across threads and watch out for crypt() calls
Sablotron 0.95 ?
zlib 1.1.4 Yes Relies upon thread-safe zalloc and zfree functions Default is to use libc's calloc/free which are thread-safe.





sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-01-14 14:29:44
Processing time 0.0131 sec