[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gnulib and threaded execution

From: Bruno Haible
Subject: Re: gnulib and threaded execution
Date: Fri, 3 Dec 2010 02:38:20 +0100
User-agent: KMail/1.9.9

Hi Ralf,

> When you try to use gnulib in threaded
> code, any process-global state can potentially cause problems, whether
> that be static data, file descriptor state, current directory, umask,
> etc.  For a lot of these data and in a lot of the cases, gnulib is safe.
> Still, it might make sense to make an effort to document exceptions to
> this rule: users might not even be aware that three levels down the
> module dependency tree, they are using something potentially unsafe.

Very true. When using fstrcmp in a multithreaded situation in msgmerge,
I had to chase the module dependencies and then look at each involved
source code file. It's doable for fstrcmp(), but when you look at
larger pieces of code, the task becomes daunting.

I would find it useful and systematic if we started to add a
section "Multithreading:" to the module descriptions. Its contents
could be a simple statement like "MT-safe", or a description like
this for iconv_open:
  A conversion descriptor can not be used in multiple threads
or for localcharset:
  Depends on global state: The current locale. This function is
  unreliable if setlocale() is called in other threads.

Filling in this information requires a review of the code, looking
at global variables, system calls, and more.

> I egrepped for '([     ]static |static [^()]*;)' (TAB inside) and
> among the first few hits (of a few hundred) I found these issues:

This is just a portion of what needs to be looked at. There's also
the global variables (use 'nm' on the object files to find them),
sigaction() system calls, fork()/exec() calls (which operate in
platform dependent manner if threads are active), and many more.

> * Unless STACK_DIRECTION is defined, gnulib/lib/alloca.c sets and uses
> STACK_DIR and find_stack_direction:addr in the first alloca call.  When
> that first call is from threads, and racing with another one, the value
> for STACK_DIRECTION may be computed wrongly, and the code may corrupt
> the stack.

You're just scratching the surface. More importantly, the 'alloca'
module cannot be used _at_all_ in code meant to be used in multiple
  1. because the stack size for threads is often smaller than
     the stack size of the main thread. (16 KB vs. 8 MB, or so.)
     You have to use module 'safe-alloca' instead.
  2. because the alloca.c code assumes that there is a "stack
     direction". This is not the case any more with GCC's new
     "split stacks" <http://gcc.gnu.org/wiki/SplitStacks>.

> * error_at_line.c has a function-static old_file_name

Additionally, if error and error_at_line are called from
multiple threads, the output will intermingle on stderr.
So, locking is necessary. In error.c it is not enabled in

> * in getloadavg.c, getloadavg_initialized should probably be a
> sig_atomic_t not a bool (no idea whether this can ever be a problem in
> practice[1]).

I'd say, this looks more like one needs to use a gl_once_t or
pthread_once_t, to guarantee that the initialization is done
at most once (and not started in parallel by several threads
if the second thread arrives when the first thread has started
the initialization and is not yet done with it).

> * register_close_hook is not thread-safe.

Yes, this should be part of the MT related documentation:
which functions are meant to be executed only once, before
anything else.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]