ATTRIBUTES
Section: Linux Programmer's Manual (7)
Updated: 2020-12-21
Page Index
NAME
attributes - POSIX safety concepts
DESCRIPTION
Note:
the text of this man page is based on the material taken from
the "POSIX Safety Concepts" section of the GNU C Library manual.
Further details on the topics described here can be found in that
manual.
Various function manual pages include a section ATTRIBUTES
that describes the safety of calling the function in various contexts.
This section annotates functions with the following safety markings:
- MT-Safe
-
MT-Safe
or
Thread-Safe functions are safe to call in the presence
of other threads.
MT, in MT-Safe, stands for Multi Thread.
-
Being MT-Safe does not imply a function is atomic, nor that it uses any
of the memory synchronization mechanisms POSIX exposes to users.
It is even possible that calling MT-Safe functions in sequence
does not yield an MT-Safe combination.
For example, having a thread call two MT-Safe
functions one right after the other does not guarantee behavior
equivalent to atomic execution of a combination of both functions,
since concurrent calls in other threads may interfere in a destructive way.
-
Whole-program optimizations that could inline functions across library
interfaces may expose unsafe reordering, and so performing inlining
across the GNU C Library interface is not recommended.
The documented
MT-Safety status is not guaranteed under whole-program optimization.
However, functions defined in user-visible headers are designed to be
safe for inlining.
- MT-Unsafe
-
MT-Unsafe
functions are not safe to call in a multithreaded programs.
Other keywords that appear in safety notes are defined in subsequent sections.
Conditionally safe features
For some features that make functions unsafe to call in certain contexts,
there are known ways to avoid the safety problem other than
refraining from calling the function altogether.
The keywords that follow refer to such features,
and each of their definitions indicates
how the whole program needs to be constrained in order to remove the
safety problem indicated by the keyword.
Only when all the reasons that
make a function unsafe are observed and addressed,
by applying the documented constraints,
does the function become safe to call in a context.
- init
-
Functions marked with
init
as an MT-Unsafe feature perform
MT-Unsafe initialization when they are first called.
-
Calling such a function at least once in single-threaded mode removes
this specific cause for the function to be regarded as MT-Unsafe.
If no other cause for that remains,
the function can then be safely called after other threads are started.
- race
-
Functions annotated with
race
as an MT-Safety issue operate on
objects in ways that may cause data races or similar forms of
destructive interference out of concurrent execution.
In some cases,
the objects are passed to the functions by users;
in others, they are used by the functions to return values to users;
in others, they are not even exposed to users.
- const
-
Functions marked with
const
as an MT-Safety issue non-atomically
modify internal objects that are better regarded as constant,
because a substantial portion of the GNU C Library accesses them without
synchronization.
Unlike
race,
which causes both readers and
writers of internal objects to be regarded as MT-Unsafe,this mark is applied to writers only.
Writers remainMT-Unsafeto call,
but the then-mandatory constness of objects they
modify enables readers to be regarded as MT-Safe(as long as no other reasons for them to be unsafe remain),
since the lack of synchronization is not a problem when the
objects are effectively constant.
-
The identifier that follows the
const
mark will appear by itself as a safety note in readers.
Programs that wish to work around this safety issue,
so as to call writers, may use a non-recursive
read-write lock
associated with the identifier, and guard
all
calls to functions marked with
const
followed by the identifier with a write lock, and
all
calls to functions marked with the identifier
by itself with a read lock.
- sig
-
Functions marked with
sig
as a MT-Safety issue
may temporarily install a signal handler for internal purposes,
which may interfere with other uses of the signal,
identified after a colon.
-
This safety problem can be worked around by ensuring that no other uses
of the signal will take place for the duration of the call.
Holding a non-recursive mutex while calling all functions that use the same
temporary signal;
blocking that signal before the call and resetting its
handler afterwards is recommended.
- term
-
Functions marked with
term
as an MT-Safety issue may change the
terminal settings in the recommended way, namely: call
tcgetattr(3),
modify some flags, and then call
tcsetattr(3),
this creates a window in which changes made by other threads are lost.
Thus, functions marked with
term
are MT-Unsafe.
-
It is thus advisable for applications using the terminal to avoid
concurrent and reentrant interactions with it,
by not using it in signal handlers or blocking signals that might use it,
and holding a lock while calling these functions and interacting
with the terminal.
This lock should also be used for mutual exclusion with
functions marked with
race:tcattr(fd),
where
fd
is a file descriptor for the controlling terminal.
The caller may use a single mutex for simplicity,
or use one mutex per terminal,
even if referenced by different file descriptors.
Other safety remarks
Additional keywords may be attached to functions,
indicating features that do not make a function unsafe to call,
but that may need to be taken into account in certain classes of programs:
- locale
-
Functions annotated with
locale
as an MT-Safety issue read from
the locale object without any form of synchronization.
Functions
annotated with
locale
called concurrently with locale changes may
behave in ways that do not correspond to any of the locales active
during their execution, but an unpredictable mix thereof.
-
We do not mark these functions as MT-Unsafe,however,
because functions that modify the locale object are marked with
const:locale
and regarded as unsafe.
Being unsafe, the latter are not to be called when multiple threads
are running or asynchronous signals are enabled,
and so the locale can be considered effectively constant
in these contexts,
which makes the former safe.
- env
-
Functions marked with
env
as an MT-Safety issue access the
environment with
getenv(3)
or similar, without any guards to ensure
safety in the presence of concurrent modifications.
-
We do not mark these functions as MT-Unsafe,however,
because functions that modify the environment are all marked with
const:env
and regarded as unsafe.
Being unsafe, the latter are not to be called when multiple threads
are running or asynchronous signals are enabled,
and so the environment can be considered
effectively constant in these contexts,
which makes the former safe.
- hostid
-
The function marked with
hostid
as an MT-Safety issue reads from the system-wide data structures that
hold the "host ID" of the machine.
These data structures cannot generally be modified atomically.
Since it is expected that the "host ID" will not normally change,
the function that reads from it
(gethostid(3))
is regarded as safe,
whereas the function that modifies it
(sethostid(3))
is marked with
const:hostid,
indicating it may require special care if it is to be called.
In this specific case,
the special care amounts to system-wide
(not merely intra-process) coordination.
- sigintr
-
Functions marked with
sigintr
as an MT-Safety issue access the
GNU C Library
_sigintr
internal data structure without any guards to ensure
safety in the presence of concurrent modifications.
-
We do not mark these functions as MT-Unsafe,however,
because functions that modify this data structure are all marked with
const:sigintr
and regarded as unsafe.
Being unsafe,
the latter are not to be called when multiple threads are
running or asynchronous signals are enabled,
and so the data structure can be considered
effectively constant in these contexts,
which makes the former safe.
- cwd
-
Functions marked with
cwd
as an MT-Safety issue may temporarily
change the current working directory during their execution,
which may cause relative pathnames to be resolved in unexpected ways in
other threads or within asynchronous signal or cancellation handlers.
-
This is not enough of a reason to mark so-marked functions as MT-Unsafe,
but when this behavior is optional (e.g.,
nftw(3)
with
FTW_CHDIR),
avoiding the option may be a good alternative to
using full pathnames or file descriptor-relative (e.g.,
openat(2))
system calls.
- :identifier
-
Annotations may sometimes be followed by identifiers,
intended to group several functions that, for example,
access the data structures in an unsafe way, as in
race
and
const,
or to provide more specific information,
such as naming a signal in a function marked with
sig.
It is envisioned that it may be applied to
lock
and
corrupt
as well in the future.
-
In most cases, the identifier will name a set of functions,
but it may name global objects or function arguments,
or identifiable properties or logical components associated with them,
with a notation such as, for example,
:buf(arg)
to denote a buffer associated with the argument
arg,
or
:tcattr(fd)
to denote the terminal attributes of a file descriptor
fd.
-
The most common use for identifiers is to provide logical groups of
functions and arguments that need to be protected by the same
synchronization primitive in order to ensure safe operation in a given
context.
- /condition
-
Some safety annotations may be conditional,
in that they only apply if a boolean expression involving arguments,
global variables or even the underlying kernel evaluates to true.
For example,
/!ps
and
/one_per_line
indicate the preceding marker only applies when argument
ps
is NULL, or global variable
one_per_line
is nonzero.
-
When all marks that render a function unsafe are
adorned with such conditions,
and none of the named conditions hold,
then the function can be regarded as safe.
SEE ALSO
pthreads(7),
signal-safety(7)
COLOPHON
This page is part of release 5.10 of the Linux
man-pages
project.
A description of the project,
information about reporting bugs,
and the latest version of this page,
can be found at
https://www.kernel.org/doc/man-pages/.