#title Apache 2.0 Thread Safety Issues #keywords Apache thread [[TableOfContents]] Copyright 2006 The Apache Software Foundation. Licensed under the [http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0] Korean Translator: ±èÁ¤±Õ ¹ø¿ªº» Âü°í »çÇ× ---- * ÀÌ ¹®¼­ÀÇ ¹ø¿ª °á°ú¹°·Î ÀÎÇÏ¿© ¹ß»ýÇÏ´Â ¹®Á¦¿¡ ´ëÇÏ¿© Ã¥ÀÓÀ» ÁöÁö ¾Ê½À´Ï´Ù. * ÀÌ ¹®¼­ÀÇ ¹ø¿ª¹°Àº ¿ø¹®ÀÇ ÀúÀ۱ǿ¡ ÀÇ°ÅÇÏ¿© ¼öÁ¤ ¹èÆ÷µÉ ¼ö ÀÖ½À´Ï´Ù. * ÀÌ ¹®¼­ÀÇ ¿øº»Àº 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 ÇÏ´Ù°í ¸»ÇÒ ¼ö´Â ¾ø½À´Ï´Ù. = Àü¿ª º¯¼ö¿Í Á¤Àû º¯¼ö = ¸ðµâÀ» ÀÛ¼ºÇÏ·Á°í Çϰųª, ¸ðµâ ¶Ç´Â 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_* ÇÔ¼ö¸¦ ÂüÁ¶ ÇϽʽÿÀ. = errno = errno ´Â ¸¶Áö¸·À¸·Î ¹ß»ýÇÑ ¿¡·¯ÀÇ ¿¡·¯ ¹øÈ£¸¦ °¡Áö°í ÀÖ´Â Àü¿ª º¯¼ö ÀÔ´Ï´Ù. ÇϳªÀÇ ¾²·¹µå°¡ errno ¸¦ ¼³Á¤ÇÏ´Â low-level ÇÔ¼ö¸¦ È£ÃâÇÏ¿´°í, ´Ù¸¥ ¾²·¹µå°¡ ÀÌ º¯¼ö¸¦ ÂüÁ¶ ÇÏ¿´À» °æ¿ì, ÂüÁ¶ÇÑ ¾²·¹µå·Î ¿øÄ¡¾Ê´Â errno ¸¦ Àü´ÞÇÏ°Ô µË´Ï´Ù. ÀÌ ¹®Á¦¸¦ ÇØ°áÇϱâ À§ÇÏ¿©, ¸ðµâ°ú ¶óÀ̺귯¸®¿¡ '''''_REENTRANT''''' »ó¼ö¸¦ ¼±¾ðÇϰųª ¶Ç´Â ÄÄÆÄÀÏ ½Ã¿¡ '''''-D_REENTRANT''''' ¿É¼ÇÀ» ÁÖ½Ç ¼ö ÀÖ½À´Ï´Ù. ÀÌ »ó¼ö´Â errno ¸¦ per-thread º¯¼ö·Î ¸¸µé¾î ÁÖ¸ç, Äڵ带 Åõ¸íÇÏ°Ô ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ »ó¼ö¸¦ ¼±¾ðÇÏ´Â °ÍÀº ´ÙÀ½°ú °°ÀÌ ÀÛµ¿À» Çϵµ·Ï ÇÕ´Ï´Ù: {{{#!vim c #define errno (*(__errno_location())) }}} ÀÌ ÄÚµåÀÇ Àǹ̴ errono ¿¡ Á¢±ÙÀ» Çϸé, libc ¿¡¼­ Á¦°øµÇ´Â __errno_location() ÀÌ È£ÃâÀÌ µË´Ï´Ù. '''''_REENTRANT''''' ¸¦ ¼³Á¤Çϸé, µ¿µîÇÑ ±â´ÉÀ» °¡Áø *_r ÇÔ¼ö¸¦ Á¦°øÇÒ °æ¿ì °­Á¦·Î ÀÌ ÇÔ¼öµé·Î ÀçÁ¤ÀÇ ÇÕ´Ï´Ù. ±×¸®°í °¡²û ¾ÈÀüÇÑ ÇÔ¼ö È£ÃâÀ» À§ÇØ getc/pubc ¸ÅÅ©·Î¸¦ º¯°æÇϱ⵵ ÇÕ´Ï´Ù. '''''_REENTRANT''''' ¸¦ Ãß°¡ÇÏ´Â °Í ¿Ü¿¡ ÀÌ ¹®Á¦¿¡ ´ëÇÏ¿© ¿µÇâÀ» ¹ÌÄ¥¼ö ÀÖ´Â ½Éº¼·Î´Â _POSIX_C_SOURCE, _THREAD_SAFE, _SVID_SOURCE, _BSD_SOURCE µîÀÌ ÀÖ½À´Ï´Ù. ÀÌ °Í¿¡ ´ëÇؼ­´Â libc ¹®¼­¸¦ ÂüÁ¶ ÇϽʽÿÀ. = 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. = Common 3rd Party Libraries = ´ÙÀ½Àº Apache ÀÇ 3th party ¸ðµâÀÌ »ç¿ëÇÏ°í ÀÖ´Â system ¶óÀ̺귯¸®ÀÇ ¸®½ºÆ® ÀÔ´Ï´Ù. ´ç½ÅÀÌ »ó¿ëÇÏ´Â ¸ðµâÀÌ ÀáÀç°ÅÀ¸·Î ¾ÈÀüÇÏÁö ¾ÊÀº ¶óÀ̺귯¸®¸¦ »ç¿ëÇÏ°í ÀÖ´Ù¸é, ldd(1) ³ª nm(1) °ú °°Àº µµ±¸¸¦ »ç¿ëÇÏ¿© È®ÀÎÀ» ÇÒ ¼ö ÀÖ½À´Ï´Ù. ´ÙÀ½ÀÇ ¿¹´Â PHP ¸¦ ÀÌ¿ëÇÏ¿© È®ÀÎÇÏ´Â °ÍÀÔ´Ï´Ù: {{{#!vim sh % 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)À» »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. = 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. ||