From: rasmus
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]
+ +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. + +
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.]
+ +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