From 69991dad00eef20ce8bb31d21b9b76b226c8bf88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Malo?= Date: Sat, 5 Apr 2003 13:23:34 +0000 Subject: [PATCH] new XML git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@99232 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/developer/thread_safety.html | 297 -------------------- docs/manual/developer/thread_safety.html.en | 279 ++++++++++++++++++ docs/manual/developer/thread_safety.xml | 274 ++++++++++++++++++ 3 files changed, 553 insertions(+), 297 deletions(-) delete mode 100644 docs/manual/developer/thread_safety.html create mode 100644 docs/manual/developer/thread_safety.html.en create mode 100644 docs/manual/developer/thread_safety.xml diff --git a/docs/manual/developer/thread_safety.html b/docs/manual/developer/thread_safety.html deleted file mode 100644 index 253edbcc7f..0000000000 --- a/docs/manual/developer/thread_safety.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - Apache 2.0 Thread Safety Issues - - - - - - -

Thread Safety

-

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, have a look at the apr_atomic_* functions and the apr_thread_mutex_* - functions. [would probably be a good idea to add an example here]

- -

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 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. [I don't see an apr_crypt() function.]

- - -

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 and nm. For - PHP, 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 to look for -individual symbols in the module.

- -

Library List

-

Please drop a note to dev@httpd.apache.org if you have additions or - corrections to this list.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LibraryVersionThread Safe?Notes
ASpell/PSpell?
Berkeley DB3.x, 4.xYesBe careful about sharing a connection across threads.
bzip2YesBoth low-level and high-level APIs are thread-safe. However, high-level API requires thread-safe access to errno.
cdb ?
C-Client Perhapsc-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 ?
ExpatYesNeed a separate parser instance per thread
FreeTDS ?
FreeType ?
GD 1.8.x ?
GD 2.0.x ?
gdbm NoErrors returned via a static gdbm_error variable
ImageMagick5.2.2YesImageMagick docs claim it is thread safe since version 5.2.2 - http://www.cise.ufl.edu/depot/www/ImageMagick/www/Changelog.html.
Imlib2 ?
libjpegv6b?
libmysqlclient YesUse mysqlclient_r library variant to ensure thread-safety. For - more information, please read http://www.mysql.com/doc/en/Threaded_clients.html.
Ming0.2a?
Net-SNMP5.0.x?
OpenLDAP2.1.xYesUse ldap_r library variant to ensure thread-safety.
OpenSSL0.96gYesRequires proper usage of CRYPTO_num_locks, CRYPTO_set_locking_callback, CRYPTO_set_id_callback
liboci8 (Oracle 8+)8.x,9.x?
pdflib5.0.xYesPDFLib 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.
libpng1.0.x?
libpng1.2.x?
libpq (PostgreSQL)7.xYesDon't share connections across threads and watch out for crypt() calls
Sablotron0.95?
zlib1.1.4YesRelies upon thread-safe zalloc and zfree functions. Default is to use libc's calloc/free which are thread-safe.
- - - diff --git a/docs/manual/developer/thread_safety.html.en b/docs/manual/developer/thread_safety.html.en new file mode 100644 index 0000000000..d50f868dba --- /dev/null +++ b/docs/manual/developer/thread_safety.html.en @@ -0,0 +1,279 @@ + + + +Apache 2.0 Thread Safety Issues - Apache HTTP Server + + + + + +
<-
+
+Apache > HTTP Server > Documentation > Version 2.1

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.

+
+ +
top
+
+

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, have a look + at the apr_atomic_* functions and the + apr_thread_mutex_* functions.

+ +
top
+
+

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.

+
top
+
+

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 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.

+ +
top
+
+

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) and + nm(1). For PHP, 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.

+
top
+
+

Library List

+

Please drop a note to dev@httpd.apache.org + if you have additions or corrections to this list.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LibraryVersionThread Safe?Notes
ASpell/PSpell ?
Berkeley DB3.x, 4.xYesBe careful about sharing a connection across threads.
bzip2 YesBoth low-level and high-level APIs are thread-safe. However, + high-level API requires thread-safe access to errno.
cdb ?
C-Client Perhapsc-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 YesNeed a separate parser instance per thread
FreeTDS ?
FreeType ?
GD 1.8.x ?
GD 2.0.x ?
gdbm NoErrors returned via a static gdbm_error + variable
ImageMagick5.2.2YesImageMagick docs claim it is thread safe since version 5.2.2 (see Change log). +
Imlib2 ?
libjpegv6b?
libmysqlclient YesUse mysqlclient_r library variant to ensure thread-safety. For + more information, please read http://www.mysql.com/doc/en/Threaded_clients.html.
Ming0.2a?
Net-SNMP5.0.x?
OpenLDAP2.1.xYesUse ldap_r library variant to ensure + thread-safety.
OpenSSL0.9.6gYesRequires proper usage of CRYPTO_num_locks, + CRYPTO_set_locking_callback, + CRYPTO_set_id_callback
liboci8 (Oracle 8+)8.x,9.x?
pdflib5.0.xYesPDFLib 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.
libpng1.0.x?
libpng1.2.x?
libpq (PostgreSQL)7.xYesDon't share connections across threads and watch out for + crypt() calls
Sablotron0.95?
zlib1.1.4YesRelies upon thread-safe zalloc and zfree functions Default is to + use libc's calloc/free which are thread-safe.
+
+ + \ No newline at end of file diff --git a/docs/manual/developer/thread_safety.xml b/docs/manual/developer/thread_safety.xml new file mode 100644 index 0000000000..b3a90cebcb --- /dev/null +++ b/docs/manual/developer/thread_safety.xml @@ -0,0 +1,274 @@ + + + + + + + +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, 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 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) and + nm(1). For PHP, 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 + if you have additions or corrections to this list.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LibraryVersionThread Safe?Notes
ASpell/PSpell ?
Berkeley DB3.x, 4.xYesBe careful about sharing a connection across threads.
bzip2 YesBoth low-level and high-level APIs are thread-safe. However, + high-level API requires thread-safe access to errno.
cdb ?
C-Client Perhapsc-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 YesNeed a separate parser instance per thread
FreeTDS ?
FreeType ?
GD 1.8.x ?
GD 2.0.x ?
gdbm NoErrors returned via a static gdbm_error + variable
ImageMagick5.2.2YesImageMagick docs claim it is thread safe since version 5.2.2 (see Change log). +
Imlib2 ?
libjpegv6b?
libmysqlclient YesUse mysqlclient_r library variant to ensure thread-safety. For + more information, please read http://www.mysql.com/doc/en/Threaded_clients.html.
Ming0.2a?
Net-SNMP5.0.x?
OpenLDAP2.1.xYesUse ldap_r library variant to ensure + thread-safety.
OpenSSL0.9.6gYesRequires proper usage of CRYPTO_num_locks, + CRYPTO_set_locking_callback, + CRYPTO_set_id_callback
liboci8 (Oracle 8+)8.x,9.x?
pdflib5.0.xYesPDFLib 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.
libpng1.0.x?
libpng1.2.x?
libpq (PostgreSQL)7.xYesDon't share connections across threads and watch out for + crypt() calls
Sablotron0.95?
zlib1.1.4YesRelies upon thread-safe zalloc and zfree functions Default is to + use libc's calloc/free which are thread-safe.
+
+
+ -- 2.40.0