HelenOS sources
This source file includes following definitions.
- atexit_handler
- initialize
- backtrace_item_hit
- bithenge_should_fail
- bithenge_failure_malloc
- bithenge_failure_realloc
- bithenge_failure_read
- bithenge_failure_lseek
- bithenge_failure_ferror
- bithenge_failure_str_ndup
- bithenge_failure_open
- bithenge_failure_fstat
#include <errno.h>
#include <execinfo.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/wait.h>
#define BITHENGE_FAILURE_DECLS_ONLY 1
#include "failure.h"
#include "common.h"
static int g_initialized = 0;
static int g_failure_index = -1;
static int g_failure_index_selected = -1;
typedef struct backtrace_item {
struct backtrace_item *next;
void *backtrace_item;
} backtrace_item_t;
static backtrace_item_t *g_backtrace_items = NULL;
static void atexit_handler(void)
{
while (g_backtrace_items) {
backtrace_item_t *first = g_backtrace_items;
g_backtrace_items = first->next;
free(first);
}
}
static inline void initialize(void)
{
g_initialized = 1;
errno_t rc = atexit(atexit_handler);
if (rc)
exit(127);
char *sel_str = getenv("BITHENGE_FAILURE_INDEX");
if (sel_str)
g_failure_index_selected = strtol(sel_str, NULL, 10);
}
static inline errno_t backtrace_item_hit(void *addr)
{
backtrace_item_t **bip;
for (bip = &g_backtrace_items; *bip; bip = &(*bip)->next) {
backtrace_item_t *bi = *bip;
if (bi->backtrace_item == addr) {
*bip = bi->next;
bi->next = g_backtrace_items;
g_backtrace_items = bi;
return 0;
}
}
backtrace_item_t *i = malloc(sizeof(*i));
if (!i)
exit(127);
i->next = g_backtrace_items;
i->backtrace_item = addr;
g_backtrace_items = i;
return 1;
}
errno_t bithenge_should_fail(void)
{
g_failure_index++;
if (!g_initialized)
initialize();
if (g_failure_index_selected != -1) {
if (g_failure_index == g_failure_index_selected)
return 1;
return 0;
}
void *trace[256];
int size = backtrace(trace, 256);
int raise_error = 0;
for (int i = 0; i < size; i++) {
if (backtrace_item_hit(trace[i]))
raise_error = 1;
}
if (!raise_error)
return 0;
if (!fork()) {
int null = open("/dev/null", O_WRONLY);
if (null == -1)
exit(127);
vfs_clone(null, STDOUT_FILENO, false);
vfs_clone(null, STDERR_FILENO, false);
vfs_put(null);
return 1;
}
int status;
wait(&status);
if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
return 0;
fprintf(stderr, "** Fake error raised here (BITHENGE_FAILURE_INDEX=%d)\n",
g_failure_index);
return 1;
}
void *bithenge_failure_malloc(size_t size)
{
if (bithenge_should_fail())
return NULL;
return malloc(size);
}
void *bithenge_failure_realloc(void *ptr, size_t size)
{
if (bithenge_should_fail())
return NULL;
return realloc(ptr, size);
}
ssize_t bithenge_failure_read(int fd, void *buf, size_t count)
{
if (bithenge_should_fail()) {
errno = EIO;
return -1;
}
return read(fd, buf, count);
}
off_t bithenge_failure_lseek(int fd, off_t offset, int whither)
{
if (bithenge_should_fail()) {
errno = EINVAL;
return (off_t) -1;
}
return lseek(fd, offset, whither);
}
errno_t bithenge_failure_ferror(FILE *stream)
{
if (bithenge_should_fail())
return 1;
return ferror(stream);
}
char *bithenge_failure_str_ndup(const char *s, size_t max_len)
{
if (bithenge_should_fail())
return NULL;
return str_ndup(s, max_len);
}
errno_t bithenge_failure_open(const char *pathname, int flags)
{
if (bithenge_should_fail()) {
errno = EACCES;
return -1;
}
return open(pathname, flags);
}
errno_t bithenge_failure_fstat(int fd, vfs_stat_t *buf)
{
if (bithenge_should_fail()) {
errno = EIO;
return -1;
}
return fstat(fd, buf);
}
HelenOS homepage, sources at GitHub