# Apache 2.0 Thread Safety Issues
When using any of the threaded mpms in Apache 2.0 it is important that every function called from Apache be thread safe. When linking in 3rd party extensions it can be difficult to determine whether the resulting server will be thread safe. Casual testing generally won't tell you this either as thread safety problems can lead to subtle race conditons that may only show up in certain conditions under heavy load.
## Global and static variables
When writing your module or when trying to determine if a module or 3rd party library is thread safe there are some common things to keep in mind.
First, you need to recognize that in a threaded model each individual thread has its own program counter, stack and registers. Local variables live on the stack, so those are fine. You need to watch out for any static or global variables. This doesn't mean that you are absolutely not allowed to use static or global variables. There are times when you actually want something to affect all threads, but generally you need to avoid using them if you want your code to be thread safe.
In the case where you have a global variable that needs to be global and accessed by all threads, be very careful when you update it. If, for example, it is an incrementing counter, you need to atomically increment it to avoid race conditions with other threads. You do this using a mutex (mutual exclusion). Lock the mutex, read the current value, increment it and write it back and then unlock the mutex. Any other thread that wants to modify the value has to first check the mutex and block until it is cleared.
If you are using [APR](http://apr.apache.org/), have a look at the `apr_atomic_*` functions and the `apr_thread_mutex_*` functions.
## errno
This is a common global variable that holds the error number of the last error that occurred. If one thread calls a low-level function that sets errno and then another thread checks it, we are bleeding error numbers from one thread into another. To solve this, make sure your module or library defines `_REENTRANT` or is compiled with `-D_REENTRANT`. This will make errno a per-thread variable and should hopefully be transparent to the code. It does this by doing something like this:
```
#define errno (*(__errno_location()))
```
which means that accessing errno will call `__errno_location()` which is provided by the libc. Setting `_REENTRANT` also forces redefinition of some other functions to their `*_r` equivalents and sometimes changes the common `getc`/`putc` macros into safer function calls. Check your libc documentation for specifics. Instead of, or in addition to `_REENTRANT` the symbols that may affect this are `_POSIX_C_SOURCE`, `_THREAD_SAFE`, `_SVID_SOURCE`, and `_BSD_SOURCE`.
## Common standard troublesome functions
Not only do things have to be thread safe, but they also have to be reentrant. `strtok()` is an obvious one. You call it the first time with your delimiter which it then remembers and on each subsequent call it returns the next token. Obviously if multiple threads are calling it you will have a problem. Most systems have a reentrant version of of the function called `strtok_r()` where you pass in an extra argument which contains an allocated `char *` which the function will use instead of its own static storage for maintaining the tokenizing state. If you are using [APR](http://apr.apache.org/) you can use `apr_strtok()`.
`crypt()` is another function that tends to not be reentrant, so if you run across calls to that function in a library, watch out. On some systems it is reentrant though, so it is not always a problem. 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
The following is a list of common libraries that are used by 3rd party Apache modules. You can check to see if your module is using a potentially unsafe library by using tools such as `ldd(1)`和`nm(1)`. For [PHP](http://www.php.net/), for example, try this:
```
% 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)
```
In addition to these libraries you will need to have a look at any libraries linked statically into the module. You can use `nm(1)` to look for individual symbols in the module.
## Library List
Please drop a note to [dev@httpd.apache.org](http://httpd.apache.org/lists.html#http-dev) if you have additions or corrections to this list.
| Library | Version | Thread Safe? | Notes |
| --- | --- | --- | --- |
| [ASpell/PSpell](http://aspell.sourceforge.net/) | ? |
| [Berkeley DB](http://www.sleepycat.com/) | 3.x, 4.x | Yes | Be careful about sharing a connection across threads. |
| [bzip2](http://sources.redhat.com/bzip2/index.html) | Yes | Both low-level and high-level APIs are thread-safe. However, high-level API requires thread-safe access to errno. |
| [cdb](http://cr.yp.to/cdb.html) | ? |
| [C-Client](http://www.washington.edu/imap/) | Perhaps | c-client uses `strtok()`和`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()`和`gethostbyname()` are thread-safe on your OS, c-client _may_ be thread-safe. |
| [cpdflib](http://www.fastio.com/) | ? |
| [libcrypt](http://www.ijg.org/files/) | ? |
| [Expat](http://expat.sourceforge.net/) | Yes | Need a separate parser instance per thread |
| [FreeTDS](http://www.freetds.org/) | ? |
| [FreeType](http://www.freetype.org/) | ? |
| [GD 1.8.x](http://www.boutell.com/gd/) | ? |
| [GD 2.0.x](http://www.boutell.com/gd/) | ? |
| [gdbm](http://www.gnu.org/software/gdbm/gdbm.html) | No | Errors returned via a static `gdbm_error` variable |
| [ImageMagick](http://www.imagemagick.org/) | 5.2.2 | Yes | ImageMagick docs claim it is thread safe since version 5.2.2 (see [Change log](http://www.cise.ufl.edu/depot/www/ImageMagick/www/Changelog.html)). |
| [Imlib2](http://www.enlightenment.org/pages/imlib2.html) | ? |
| [libjpeg](http://www.ijg.org/files/) | v6b | ? |
| [libmysqlclient](http://mysql.com) | Yes | Use mysqlclient_r library variant to ensure thread-safety. For more information, please read [http://www.mysql.com/doc/en/Threaded_clients.html](http://www.mysql.com/doc/en/Threaded_clients.html). |
| [Ming](http://www.opaque.net/ming/) | 0.2a | ? |
| [Net-SNMP](http://net-snmp.sourceforge.net/) | 5.0.x | ? |
| [OpenLDAP](http://www.openldap.org/) | 2.1.x | Yes | Use `ldap_r` library variant to ensure thread-safety. |
| [OpenSSL](http://www.openssl.org/) | 0.9.6g | Yes | Requires proper usage of `CRYPTO_num_locks`, `CRYPTO_set_locking_callback`, `CRYPTO_set_id_callback` |
| [liboci8 (Oracle 8+)](http://www.oracle.com/) | 8.x,9.x | ? |
| [pdflib](http://pdflib.com/) | 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](http://www.pdflib.com/products/pdflib/index.html). |
| [libpng](http://www.libpng.org/pub/png/libpng.html) | 1.0.x | ? |
| [libpng](http://www.libpng.org/pub/png/libpng.html) | 1.2.x | ? |
| [libpq (PostgreSQL)](http://www.postgresql.org/idocs/index.php?libpq-threading.html) | 7.x | Yes | Don't share connections across threads and watch out for `crypt()` calls |
| [Sablotron](http://www.gingerall.com/charlie/ga/xml/p_sab.xml) | 0.95 | ? |
| [zlib](http://www.gzip.org/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. |
- Apache HTTP Server Version 2.2 文檔 [最后更新:2006年3月21日]
- 版本說明
- 從1.3升級到2.0
- 從2.0升級到2.2
- Apache 2.2 新特性概述
- Apache 2.0 新特性概述
- The Apache License, Version 2.0
- 參考手冊
- 編譯與安裝
- 啟動Apache
- 停止和重啟
- 配置文件
- 配置段(容器)
- 緩沖指南
- 服務器全局配置
- 日志文件
- 從URL到文件系統的映射
- 安全方面的提示
- 動態共享對象(DSO)支持
- 內容協商
- 自定義錯誤響應
- 地址和端口的綁定(Binding)
- 多路處理模塊
- Apache的環境變量
- Apache處理器的使用
- 過濾器(Filter)
- suEXEC支持
- 性能方面的提示
- URL重寫指南
- Apache虛擬主機文檔
- 基于主機名的虛擬主機
- 基于IP地址的虛擬主機
- 大批量虛擬主機的動態配置
- 虛擬主機示例
- 深入研究虛擬主機的匹配
- 文件描述符限制
- 關于DNS和Apache
- 常見問題
- 經常問到的問題
- Apache的SSL/TLS加密
- SSL/TLS高強度加密:緒論
- SSL/TLS高強度加密:兼容性
- SSL/TLS高強度加密:如何...?
- SSL/TLS Strong Encryption: FAQ
- 如何.../指南
- 認證、授權、訪問控制
- CGI動態頁面
- 服務器端包含入門
- .htaccess文件
- 用戶網站目錄
- 針對特定平臺的說明
- 在Microsoft Windows中使用Apache
- 在Microsoft Windows上編譯Apache
- Using Apache With Novell NetWare
- Running a High-Performance Web Server on HPUX
- The Apache EBCDIC Port
- 服務器和支持程序
- httpd - Apache超文本傳輸協議服務器
- ab - Apache HTTP服務器性能測試工具
- apachectl - Apache HTTP服務器控制接口
- apxs - Apache 擴展工具
- configure - 配置源代碼樹
- dbmmanage - 管理DBM格式的用戶認證文件
- htcacheclean - 清理磁盤緩沖區
- htdbm - 操作DBM密碼數據庫
- htdigest - 管理用于摘要認證的用戶文件
- httxt2dbm - 生成RewriteMap指令使用的dbm文件
- htpasswd - 管理用于基本認證的用戶文件
- logresolve - 解析Apache日志中的IP地址為主機名
- rotatelogs - 滾動Apache日志的管道日志程序
- suexec - 在執行外部程序之前切換用戶
- 其他程序
- 雜項文檔
- 與Apache相關的標準
- Apache模塊
- 描述模塊的術語
- 描述指令的術語
- Apache核心(Core)特性
- Apache MPM 公共指令
- Apache MPM beos
- Apache MPM event
- Apache MPM netware
- Apache MPM os2
- Apache MPM prefork
- Apache MPM winnt
- Apache MPM worker
- Apache模塊 mod_actions
- Apache模塊 mod_alias
- Apache模塊 mod_asis
- Apache模塊 mod_auth_basic
- Apache模塊 mod_auth_digest
- Apache模塊 mod_authn_alias
- Apache模塊 mod_authn_anon
- Apache模塊 mod_authn_dbd
- Apache模塊 mod_authn_dbm
- Apache模塊 mod_authn_default
- Apache模塊 mod_authn_file
- Apache模塊 mod_authnz_ldap
- Apache模塊 mod_authz_dbm
- Apache模塊 mod_authz_default
- Apache模塊 mod_authz_groupfile
- Apache模塊 mod_authz_host
- Apache模塊 mod_authz_owner
- Apache模塊 mod_authz_user
- Apache模塊 mod_autoindex
- Apache模塊 mod_cache
- Apache模塊 mod_cern_meta
- Apache模塊 mod_cgi
- Apache模塊 mod_cgid
- Apache模塊 mod_charset_lite
- Apache模塊 mod_dav
- Apache模塊 mod_dav_fs
- Apache模塊 mod_dav_lock
- Apache模塊 mod_dbd
- Apache模塊 mod_deflate
- Apache模塊 mod_dir
- Apache模塊 mod_disk_cache
- Apache模塊 mod_dumpio
- Apache模塊 mod_echo
- Apache模塊 mod_env
- Apache模塊 mod_example
- Apache模塊 mod_expires
- Apache模塊 mod_ext_filter
- Apache模塊 mod_file_cache
- Apache模塊 mod_filter
- Apache模塊 mod_headers
- Apache模塊 mod_ident
- Apache模塊 mod_imagemap
- Apache模塊 mod_include
- Apache模塊 mod_info
- Apache模塊 mod_isapi
- Apache模塊 mod_ldap
- Apache模塊 mod_log_config
- Apache模塊 mod_log_forensic
- Apache模塊 mod_logio
- Apache模塊 mod_mem_cache
- Apache模塊 mod_mime
- Apache模塊 mod_mime_magic
- Apache模塊 mod_negotiation
- Apache模塊 mod_nw_ssl
- Apache模塊 mod_proxy
- Apache模塊 mod_proxy_ajp
- Apache模塊 mod_proxy_balancer
- Apache模塊 mod_proxy_connect
- Apache模塊 mod_proxy_ftp
- Apache模塊 mod_proxy_http
- Apache模塊 mod_rewrite
- Apache模塊 mod_setenvif
- Apache模塊 mod_so
- Apache模塊 mod_speling
- Apache模塊 mod_ssl
- Apache模塊 mod_status
- Apache模塊 mod_suexec
- Apache模塊 mod_unique_id
- Apache模塊 mod_userdir
- Apache模塊 mod_usertrack
- Apache模塊 mod_version
- Apache模塊 mod_vhost_alias
- Developer Documentation for Apache 2.0
- Apache 1.3 API notes
- Debugging Memory Allocation in APR
- Documenting Apache 2.0
- Apache 2.0 Hook Functions
- Converting Modules from Apache 1.3 to Apache 2.0
- Request Processing in Apache 2.0
- How filters work in Apache 2.0
- Apache 2.0 Thread Safety Issues
- 詞匯和索引
- 詞匯表
- 指令索引
- 指令速查
- 模塊索引
- 站點導航