Defect report #4nn

Previous Defect Report < - > Next Defect Report

Submitter: Jens Gustedt
Submission Date:
2012-10-08 Source:
Reference Document: N/A
Version: 1.0
Date: 2012-10-08
Subject: underspecification of thread functions with void return


There is are several thread functions in C11 that don't provide return values: call_once, cnd_destroy, mtx_destroy, tss_delete, and thrd_yield. These functions can never fail.

On the other hand it is easily imaginable that for given implementations there might be conditions that have these functions fail. In particular first four refer to objects or structures of some kind and have to suppose that these are valid.


Importance of compatibility with other thread interfaces

POSIX threads have return types for the corresponding calls that may return valuable information to the application. Wrappers around POSIX threads currently have to ignore that information and are not able to return it, nor are they allowed to output a runtime diagnostic or to abort the program.

Implementations of C11 threads that use POSIX threads underneath in a shallow interface (e.g through inline functions) may face multiple warnings from compilers or code analysers about ignored return values.

Importance of the possibility of failure

It is unlikely that an implementation will be able to implement these functions in ways that guarantees their successful invocation under all circumstances. The standard not being precise on the possible conditions for failure opens the door to a great variety of behavior of these calls in such a case. It is possible that that variety of strategies to cope with errors is unavoidable, but the standard should at least note the most common conditions and force implementation defined behavior in these cases.

Suggested Technical Corrigendum

There are basically two main strategies to overcome that difficulty. The first is to change the interfaces and to allow them to return an int-error code. The second to specify for each call under what circumstances the behavior becomes undefined.

Both solutions require an analysis of the conditions under which these functions may fail. Fortunately, POSIX also provides us with such an analysis so the text could be more or less copied from there.

(0) common corrigendum proposed for both alternatives


The behavior of call_once is undefined if flag has automatic storage duration or is not initialized by ONCE_FLAG_INIT.


A destroyed condition variable object can be reinitialized using cnd_init; the results of otherwise referencing the object after it has been destroyed are undefined.
It shall be safe to destroy an initialized condition variable object upon which no threads are currently blocked. Attempting to destroy a condition variable object upon which other threads are currently blocked results in failure of the call.


A destroyed mutex object can be reinitialized using mtx_init; the results of otherwise referencing the object after it has been destroyed are undefined.
Attempting to destroy a locked mutex or one that is referenced by another thread that is blocked in a call to cnd_wait results in failure of the call.


Any attempt to use key following the call to tss_delete results in failure of the call.

Then, the two alternatives would be to add either of the two following snipets to the sections for each of the functions:

(1) UB

A failing call results in undefined behavior.

(2) Changing the return type from void to int would not break existing code, since such calls could have up to now only be placed in void-context. Some compilers might add warnings after the corrigendum, though, for unused return values. For each of the functions in question add something equivalent to

... change the return type to int ...
An implementation should specify if it is able to handle failures and what error indications are returned in such a case by the function. If a particular implementation isn't able to handle failures the behavior becomes undefined.

Previous Defect Report < - > Next Defect Report