RRDTHREADS(1) rrdtool RRDTHREADS(1)

rrdthreads - Provisions for linking the RRD library to use in multi-threaded programs

Using librrd in multi-threaded programs requires some extra precautions, as the RRD library in its original form was not thread-safe at all. This document describes requirements and pitfalls on the way to use the multi-threaded version of librrd in your own programs. It also gives hints for future RRD development to keep the library thread-safe.

Currently only some RRD operations are implemented in a thread-safe way. They all end in the usual ""_r"" suffix.

In order to use librrd in multi-threaded programs you must:

Some precautions must be followed when developing RRD from now on:

Only use thread-safe functions in library code. Many often used libc functions aren't thread-safe. Take care in the following situations or when using the following library functions:
  • Direct calls to strerror() must be avoided: use rrd_strerror() instead, it provides a per-thread error message.
  • The "getpw*", "getgr*", "gethost*" function families (and some more "get*" functions) are not thread-safe: use the *"_r" variants
  • Time functions: "asctime", "ctime", "gmtime", "localtime": use *"_r" variants
  • "strtok": use "strtok_r"
  • "tmpnam": use "tmpnam_r"
  • Many others (lookup documentation)
  • A header file named rrd_is_thread_safe.h is provided that works with the GNU C-preprocessor to "poison" some of the most common non-thread-safe functions using the "#pragma GCC poison" directive. Just include this header in source files you want to keep thread-safe.
  • Do not introduce global variables!

    If you really, really have to use a global variable you may add a new field to the "rrd_context" structure and modify rrd_error.c, rrd_thread_safe.c and rrd_non_thread_safe.c

  • Do not use "getopt" or "getopt_long" in *"_r" (neither directly nor indirectly).

    "getopt" uses global variables and behaves badly in a multi-threaded application when called concurrently. Instead provide a *_r function taking all options as function parameters. You may provide argc and **argv arguments for variable length argument lists. See "rrd_update_r" as an example.

  • Do not use the "rrd_parsetime" function!

    It uses lots of global variables. You may use it in functions not designed to be thread-safe, like in functions wrapping the "_r" version of some operation (e.g., "rrd_create", but not in "rrd_create_r")

Currently there exist thread-safe variants of "rrd_update", "rrd_create", "rrd_dump", "rrd_info", "rrd_last", and "rrd_fetch".

Peter Stamfest <peter@stamfest.at>

2024-03-31 1.7.2