author | Alberto Bertogli
<albertito@blitiri.com.ar> 2012-03-27 23:51:45 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2012-03-27 23:59:12 UTC |
parent | e96826c35845057b289d3e4d0071d2acaa7062c0 |
.gitignore | +3 | -0 |
doc/guide.rst | +19 | -19 |
libfiu/Makefile | +7 | -1 |
libfiu/doxygen/Doxyfile.base.in | +204 | -0 |
libfiu/doxygen/Doxyfile.internal | +7 | -0 |
libfiu/doxygen/Doxyfile.public | +8 | -0 |
libfiu/doxygen/Makefile | +33 | -0 |
libfiu/fiu-control.h | +53 | -37 |
libfiu/fiu.c | +2 | -2 |
libfiu/fiu.h | +27 | -18 |
libfiu/libfiu.3 | +7 | -3 |
diff --git a/.gitignore b/.gitignore index 24e7bb9..72d4573 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ libfiu/libfiu.pc libfiu/libfiu.so libfiu/libfiu.so.* libfiu/build-flags +libfiu/doxygen/doc.internal +libfiu/doxygen/doc.public +libfiu/doxygen/Doxyfile.base preload/posix/*.o preload/posix/*.so preload/posix/build-flags diff --git a/doc/guide.rst b/doc/guide.rst index c401b46..7b3d2cb 100644 --- a/doc/guide.rst +++ b/doc/guide.rst @@ -20,9 +20,8 @@ libfiu is a library that you can use to add fault injection to your code. It aims to be easy to use by means of a simple API, with minimal code impact and little runtime overhead when enabled. -By minimal code impact I mean that the modifications you have to do to your -code (and build system) in order to support libfiu should be as little -intrusive as possible. +That means that the modifications you have to do to your code (and build +system) in order to support libfiu should be as little intrusive as possible. Code overview @@ -31,8 +30,8 @@ Code overview Let's take a look to a small (fictitious) code sample to see what's the general idea behind libfiu. -Let's say you have this code that checks if there's enough free space to store -a given file:: +Assume that you have this code that checks if there's enough free space to +store a given file:: size_t free_space() { [code to find out how much free space there is] @@ -46,9 +45,9 @@ a given file:: return true; } -As you can see, with current disk sizes, it's very, very strange that a disk -runs out of free space. So the scenario where *free_space()* returns 0 is hard -to test. With libfiu, you can modify that code into:: +With current disk sizes, it's very unusual to ran out of free space, which +makes the scenario where *free_space()* returns 0 hard to test. With libfiu, +you can do the following small addition:: size_t free_space() { fiu_return_on("no_free_space", 0); @@ -64,9 +63,10 @@ to test. With libfiu, you can modify that code into:: return true; } -There, you've just created a *point of failure* identified by the name -"no_free_space", and said that when that point of failure is enabled, the -function will return 0. +The *fiu_return_on()* annotation is the only change you need to make to your +code to create a *point of failure*, which is identified by the name +**no_free_space**. When that point of failure is enabled, the function will +return 0. In your testing code, you can now do this:: @@ -75,13 +75,13 @@ In your testing code, you can now do this:: assert(file_fits("tmpfile") == false); The first line initializes the library, and the second *enables* the point of -failure. As the point of failure is enabled, *free_space()* will return 0, so -you can test how your code behaves under that condition, which was otherwise -hard to trigger. +failure. When the point of failure is enabled, *free_space()* will return 0, +so you can test how your code behaves under that condition, which was +otherwise hard to trigger. -As you can see, libfiu's API has two "sides": a core API and a control API. -The core API is used inside the code to be fault injected. The control API is -used inside the testing code, in order to control the injection of failures. +libfiu's API has two "sides": a core API and a control API. The core API is +used inside the code to be fault injected. The control API is used inside the +testing code, in order to control the injection of failures. In the example above, *fiu_return_on()* is a part of the core API, and *fiu_enable()* is a part of the control API. @@ -99,7 +99,7 @@ The build system The first thing to do is to enable your build system to use libfiu. Usually, you do not want to make libfiu a runtime or build-time dependency, because -it's a testing library. +it's often only used for testing. To that end, you should copy *fiu-local.h* into your source tree, and then create an option to do a *fault injection build* that #defines the constant @@ -121,7 +121,7 @@ First, you should ``#include "fiu-local.h"`` in the files you want to add points of failure to. That header allows you to avoid libfiu as a build-time dependency, as mentioned in the last section. -Then, to insert points of failure, you sprinkle your code with calls like +Then, to insert points of failure, sprinkle your code with calls like ``fiu_return_on("name", -1)``, ``fiu_exit_on("name")``, or more complex code using ``fiu_fail("name")``. See the libfiu's manpage for the details on the API. diff --git a/libfiu/Makefile b/libfiu/Makefile index ed98034..07ebfca 100644 --- a/libfiu/Makefile +++ b/libfiu/Makefile @@ -109,14 +109,20 @@ $(OBJS): build-flags .c.o: $(NICE_CC) $(ALL_CFLAGS) -c $< -o $@ + +doxygen: + $(MAKE) LIB_VER=$(LIB_VER) -C doxygen + + clean: rm -f libfiu.pc $(OBJS) libfiu.so libfiu.so.$(LIB_VER) libfiu.a rm -f *.bb *.bbg *.da *.gcov *.gcda *.gcno gmon.out build-flags + $(MAKE) -C doxygen $@ .PHONY: default all libs \ install-lib install-man install \ uninstall-lib uninstall-man uninstall \ - clean \ + doxygen clean \ .force-build-flags diff --git a/libfiu/doxygen/Doxyfile.base.in b/libfiu/doxygen/Doxyfile.base.in new file mode 100644 index 0000000..1c8f6e8 --- /dev/null +++ b/libfiu/doxygen/Doxyfile.base.in @@ -0,0 +1,204 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = libfiu +PROJECT_NUMBER = ++VERSION++ +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = ../ +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c *.h *.doxy +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = NO +USE_HTAGS = NO +VERBATIM_HEADERS = YES +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = YES +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = YES +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NONE +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = FIU_ENABLE +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/libfiu/doxygen/Doxyfile.internal b/libfiu/doxygen/Doxyfile.internal new file mode 100644 index 0000000..6066429 --- /dev/null +++ b/libfiu/doxygen/Doxyfile.internal @@ -0,0 +1,7 @@ +@INCLUDE = Doxyfile.base +PROJECT_NAME = "libfiu (internal)" +OUTPUT_DIRECTORY = doc.internal +EXTRACT_ALL = YES +EXTRACT_STATIC = YES +INTERNAL_DOCS = YES + diff --git a/libfiu/doxygen/Doxyfile.public b/libfiu/doxygen/Doxyfile.public new file mode 100644 index 0000000..168bb3c --- /dev/null +++ b/libfiu/doxygen/Doxyfile.public @@ -0,0 +1,8 @@ +@INCLUDE = Doxyfile.base +PROJECT_NAME = "libfiu (public)" +OUTPUT_DIRECTORY = doc.public +EXTRACT_ALL = YES +EXTRACT_STATIC = NO +INTERNAL_DOCS = NO +INPUT = ../fiu.h ../fiu-control.h + diff --git a/libfiu/doxygen/Makefile b/libfiu/doxygen/Makefile new file mode 100644 index 0000000..daa51cd --- /dev/null +++ b/libfiu/doxygen/Makefile @@ -0,0 +1,33 @@ + +ifneq ($(V), 1) + NICE_DOXYGEN = @echo " DOXYGEN $@"; doxygen +else + NICE_DOXYGEN = doxygen +endif + + +default: all + +all: public internal + +# $(LIB_VER) must be defined externally if we want the generated docs to +# specify a version number. Usually, this Makefile will be invoked by +# libfiu's, which has that variable properly defined. +Doxyfile.base: Doxyfile.base.in + @echo "generating Doxyfile.base" + @cat Doxyfile.base.in | \ + sed 's@++VERSION++@$(LIB_VER)@g' \ + > Doxyfile.base + +public: Doxyfile.base + $(NICE_DOXYGEN) Doxyfile.public + +internal: Doxyfile.base + $(NICE_DOXYGEN) Doxyfile.internal + +clean: + rm -rf doc.internal doc.public Doxyfile.base + + +.PHONY: all clean default doxygen internal public + diff --git a/libfiu/fiu-control.h b/libfiu/fiu-control.h index 30ed4f1..1a8dfff 100644 --- a/libfiu/fiu-control.h +++ b/libfiu/fiu-control.h @@ -1,4 +1,11 @@ +/** @file + * + * This header contains the control API. + * It should be used for controlling the injection of failures, usually when + * writing tests. + */ + #ifndef _FIU_CONTROL_H #define _FIU_CONTROL_H @@ -6,71 +13,80 @@ extern "C" { #endif -/* - * Control API for libfiu - */ /* Flags for fiu_enable*() */ -#define FIU_ONETIME 1 /* Only fail once */ + +/** Only fail once; the point of failure will be automatically disabled + * afterwards. */ +#define FIU_ONETIME 1 -/* Enables the given point of failure. That makes it always fail. +/** Enables the given point of failure unconditionally. * - * - name: point of failure name. - * - failnum: what will fiu_fail() return, must be != 0. - * - failinfo: what will fiu_failinfo() return. - * - flags: flags. - * - returns: 0 if success, < 0 otherwise. + * @param name Name of the point of failure to enable. + * @param failnum What will fiu_fail() return, must be != 0. + * @param failinfo What will fiu_failinfo() return. + * @param flags Flags. + * @returns 0 if success, < 0 otherwise. */ int fiu_enable(const char *name, int failnum, void *failinfo, unsigned int flags); -/* Enables the given point of failure, with the given probability. That makes - * it fail with the given probablity. +/** Enables the given point of failure, with the given probability. That makes + * it fail with the given probability. * - * - name: point of failure name. - * - failnum: what will fiu_fail() return, must be != 0. - * - failinfo: what will fiu_failinfo() return. - * - flags: flags. - * - probability: probability a fiu_fail() call will return failnum, + * @param name Name of the point of failure to enable. + * @param failnum What will fiu_fail() return, must be != 0. + * @param failinfo What will fiu_failinfo() return. + * @param flags Flags. + * @param probability Probability a fiu_fail() call will return failnum, * between 0 (never fail) and 1 (always fail). As a special fast case, -1 * can also be used to always fail. - * - returns: 0 if success, < 0 otherwise. */ + * @returns 0 if success, < 0 otherwise. + */ int fiu_enable_random(const char *name, int failnum, void *failinfo, unsigned int flags, float probability); -/** Type of external callback functions. They must return 0 to indicate not to - * fail, != 0 to indicate otherwise. Can modify failnum, failinfo and flags, - * in order to alter the values of the point of failure. */ +/** Type of external callback functions. + * They must return 0 to indicate not to fail, != 0 to indicate otherwise. Can + * modify failnum, failinfo and flags, in order to alter the values of the + * point of failure. */ typedef int external_cb_t(const char *name, int *failnum, void **failinfo, unsigned int *flags); -/* Enables the given point of failure, leaving the decision whether to fail or - * not to the given external function. +/** Enables the given point of failure, leaving the decision whether to fail + * or not to the given external function. * - * - name: point of failure name. - * - failnum: what will fiu_fail() return, must be != 0. - * - failinfo: what will fiu_failinfo() return. - * - flags: flags. - * - external_cb: function to call to determine whether fail or not. */ + * @param name Name of the point of failure to enable. + * @param failnum What will fiu_fail() return, must be != 0. + * @param failinfo What will fiu_failinfo() return. + * @param flags Flags. + * @param external_cb Function to call to determine whether to fail or not. + * @returns 0 if success, < 0 otherwise. + */ int fiu_enable_external(const char *name, int failnum, void *failinfo, unsigned int flags, external_cb_t *external_cb); -/* Disables the given point of failure. That makes it NOT fail. +/** Disables the given point of failure. That makes it NOT fail. * - * - name: point of failure name. - * - returns: 0 if success, < 0 otherwise. */ + * @param name Name of the point of failure to disable. + * @returns 0 if success, < 0 otherwise. + */ int fiu_disable(const char *name); -/* Enables remote control over a named pipe that begins with the given - * basename. "-$PID" will be appended to it to form the final path. After the - * process dies, the pipe will be removed. If the process forks, a new pipe - * will be created. +/** Enables remote control over a named pipe. + * + * The name pipe path will begin with the given basename. "-$PID" will be + * appended to it to form the final path. After the process dies, the pipe + * will be removed. If the process forks, a new pipe will be created. + * + * Once this function has been called, the fiu-ctrl utility can be used to + * control the points of failure externally. * - * - basename: base path to use in the creation of the named pipes. - * - returns: 0 on success, -1 on errors. */ + * @param basename Base path to use in the creation of the named pipes. + * @returns 0 on success, -1 on errors. */ int fiu_rc_fifo(const char *basename); diff --git a/libfiu/fiu.c b/libfiu/fiu.c index 0ae2ec0..1a7e0a4 100644 --- a/libfiu/fiu.c +++ b/libfiu/fiu.c @@ -259,8 +259,8 @@ int fiu_fail(const char *name) rec_count++; - /* we must do this before acquiring the lock and calling any - * (potentially wrapped) functions */ + /* We must do this before acquiring the lock and calling any + * (potentially wrapped) functions. */ if (rec_count > 1) { rec_count--; return 0; diff --git a/libfiu/fiu.h b/libfiu/fiu.h index a625a37..7659b7f 100644 --- a/libfiu/fiu.h +++ b/libfiu/fiu.h @@ -1,11 +1,11 @@ -/* libfiu - Fault Injection in Userspace +/** @file * - * This header, part of libfiu, contains the API that your project should use. + * This header contains the API that your project should use when defining + * points of failure in your real (non-testing) code. * * If you want to avoid having libfiu as a mandatory build-time dependency, - * you should include fiu-local.h in your project, and #include it instead of - * this. + * you should add fiu-local.h to your project, and \#include that instead. */ #ifndef _FIU_H @@ -20,25 +20,34 @@ extern "C" { #endif -/* Initializes the library. +/** Initializes the library. * - * - flags: unused. - * - returns: 0 if success, < 0 if error. */ + * Must be called before any other library function. It is safe to invoke it + * more than once. + * + * @param flags Unused. + * @returns 0 if success, < 0 if error. + */ int fiu_init(unsigned int flags); -/* Returns the failure status of the given point of failure. +/** Returns the failure status of the given point of failure. * - * - name: point of failure name. - * - returns: the failure status (0 means it should not fail). */ + * @param name Point of failure name. + * @returns The failure status (0 means it should not fail). + */ int fiu_fail(const char *name); -/* Returns the information associated with the last failure. +/** Returns the information associated with the last failure. * - * - returns: the information associated with the last fail, or NULL if there - * isn't one. */ + * Please note that this function is thread-safe and thread-local, so the + * information returned will be for the last failure in the same thread. + * + * @returns The information associated with the last failure, or NULL if + * there isn't one. + */ void *fiu_failinfo(void); -/* Performs the given action when the given point of failure fails. Mostly +/** Performs the given action when the given point of failure fails. Mostly * used in the following macros. */ #define fiu_do_on(name, action) \ do { \ @@ -47,10 +56,10 @@ void *fiu_failinfo(void); } \ } while (0) -/* Exits the program when the given point of failure fails. */ +/** Exits the program when the given point of failure fails. */ #define fiu_exit_on(name) fiu_do_on(name, exit(EXIT_FAILURE)) -/* Makes the function return the given retval when the given point of failure +/** Makes the function return the given retval when the given point of failure * fails. */ #define fiu_return_on(name, retval) fiu_do_on(name, return retval) @@ -60,8 +69,8 @@ void *fiu_failinfo(void); #endif #else -/* fiu not enabled, this should match fiu-local.h but we don't include it - * because it includes us assuming we're installed system-wide */ +/* These are used when fiu not enabled. They should match fiu-local.h but we + * don't include it to avoid a circular dependency. */ #define fiu_init(flags) 0 #define fiu_fail(name) 0 diff --git a/libfiu/libfiu.3 b/libfiu/libfiu.3 index b7e3616..32e0939 100644 --- a/libfiu/libfiu.3 +++ b/libfiu/libfiu.3 @@ -46,7 +46,10 @@ in the distribution. .SS CORE API To use the core API, you should -.IR "#include <fiu.h>" . +.I "#include <fiu.h>" +(or +.IR "<fiu-local.h>" , +see below). Because fault injection is usually a debugging/testing facility, unwanted at runtime, some special considerations were taken to minimize the impact of the @@ -55,7 +58,7 @@ core API. First of all, if is not defined, then fiu.h will define empty stubs for all the core API, effectively disabling fault injection completely. -Also, a special header +Also, the special header .I fiu-local.h is shipped with libfiu. It is meant to be included in your project to avoid having libfiu as a mandatory build-time dependency. You can add it to your @@ -84,7 +87,8 @@ runtime using the control API. .TP .BI "fiu_failinfo()" Returns the information associated with the last failure, or NULL if there -isn't one. +isn't one. This function is thread-aware and will only return information +about failures in the calling thread. .TP .BI "fiu_do_on(" name ", " action ") [macro]"