Error Handling¶
All functions in this project use a common scheme for return codes and error handling.
All functions, except for getters and setters, return the type osd_result
.
A return code of OSD_OK
indicates a successful function call, any other return value indicates an error.
The error types are given as one of the OSD_ERROR_*.
Use OSD_SUCCEEDED
to check if a function call was successful, and OSD_FAILED
to check if it failed.
Use of assertions¶
Using assertions within libosd causes the application using libosd to crash. A crash can be a good way to fail early, however, it may be used only for non-recoverable errors or programming errors. In consequence, libosd makes use of assertions to check for internal errors (i.e. bugs in libosd), or to check for violated API calling conventions. However, assertions are not used to check for invalid or missing input data from known-to-be-unreliable sources (e.g. from the network, from a user or from the file system).
Assertions are used in the following cases:
- API calling conventions are not followed.
- Violoated pre- or postconditions: the internal state when entering or exiting a function isn’t what was expected.
Assertions are not used in in the following scenarios:
- User input to a function is not valid.
- Unexpected data was received from the network, from the file system, or similar sources.
- The communication broke down.
Handling memory allocation errors¶
In general, out of memory errors returned from malloc() and similar functions are fatal, i.e. cause the program using libosd to crash. This is motivated by the fact that these errors occur very rarely and the associated error handling path is rarely executed and tested.
In some cases where larger memory allocations are required, especially contiguous chunks of memory, error handling is implemented and fallback paths are used.
Example¶
#include <osd/osd.h>
#include <assert.h>
osd_result rv;
// common case: pass error on to calling function
rv = osd_some_call();
if (OSD_FAILED(rv)) {
return rv;
}
// check for a successful call
rv = osd_another_call();
if (OSD_SUCCEEDED(rv)) {
printf("Call successful!\n");
}
// A failing call may not happen and hence is a bug in OSD: use assert()
rv = osd_must_succeed_call();
assert(OSD_SUCCEEDED(rv));
// fatal malloc: assert if the memory allocation failed
char* some_data = malloc(sizeof(char) * 100));
assert(some_data);
Public Interface¶
-
typedef int
osd_result
¶ Standard return type
-
OSD_OK
¶ Return code: The operation was successful
-
OSD_ERROR_FAILURE
¶ Return code: Generic (unknown) failure
-
OSD_ERROR_DEVICE_ERROR
¶ Return code: debug system returned a failure
-
OSD_ERROR_DEVICE_INVALID_DATA
¶ Return code: received invalid or malformed data from device
-
OSD_ERROR_COM
¶ Return code: failed to communicate with device
-
OSD_ERROR_TIMEDOUT
¶ Return code: operation timed out
-
OSD_ERROR_NOT_CONNECTED
¶ Return code: not connected to the device
-
OSD_ERROR_PARTIAL_RESULT
¶ Return code: this is a partial result, not all requested data was obtained
-
OSD_ERROR_ABORTED
¶ Return code: operation aborted
-
OSD_ERROR_CONNECTION_FAILED
¶ Return code: connection failed
-
OSD_ERROR_OOM
¶ Return code: Out of memory
-
OSD_ERROR_FILE
¶ Return code: file operation failed
-
OSD_ERROR_MEM_VERIFY_FAILED
¶ Return code: memory verification failed
-
OSD_ERROR_WRONG_MODULE
¶ Return code: unexpected module type
-
OSD_FAILED
(rv)¶ Return true if |rv| is an error code
-
OSD_SUCCEEDED
(rv)¶ Return true if |rv| is a successful return code