static int ctdb_test_poll(struct pollfd *fds, nfds_t nfds, int timeout,
const char *location)
{
- if (should_i_fail("poll")) {
+ if (should_i_fail("poll", location)) {
errno = EINVAL;
return -1;
}
static void *ctdb_test_malloc(size_t size, const char *location)
{
- if (should_i_fail("malloc")) {
+ if (should_i_fail("malloc", location)) {
errno = ENOMEM;
return NULL;
}
static void *ctdb_test_realloc(void *ptr, size_t size, const char *location)
{
- if (should_i_fail("realloc")) {
+ if (should_i_fail("realloc", location)) {
errno = ENOMEM;
return NULL;
}
static ssize_t ctdb_test_read(int fd, void *buf, size_t count,
const char *location)
{
- if (should_i_fail("read")) {
+ if (should_i_fail("read", location)) {
errno = EBADF;
return -1;
}
static ssize_t ctdb_test_write(int fd, const void *buf, size_t count,
const char *location)
{
- if (should_i_fail("write")) {
+ if (should_i_fail("write", location)) {
errno = EBADF;
return -1;
}
static int ctdb_test_socket(int domain, int type, int protocol,
const char *location)
{
- if (should_i_fail("socket")) {
+ if (should_i_fail("socket", location)) {
errno = EINVAL;
return -1;
}
static int ctdb_test_connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen, const char *location)
{
- if (should_i_fail("connect")) {
+ if (should_i_fail("connect", location)) {
errno = EINVAL;
return -1;
}
tdb_hash_func hash_fn,
const char *location)
{
- if (should_i_fail("tdb_open_ex")) {
+ if (should_i_fail("tdb_open_ex", location)) {
errno = ENOENT;
return NULL;
}
return true;
}
+static char *make_location(const char *func, const char *caller)
+{
+ const char *afterslash;
+
+ afterslash = strrchr(caller, '/');
+ if (afterslash)
+ afterslash++;
+ else
+ afterslash = caller;
+ return talloc_asprintf(working, "%s(%s)", func, afterslash);
+}
+
/* Should I fail at this point? Once only: it would be too expensive
* to fail at every possible call. */
-bool should_i_fail_once(const char *location)
+bool should_i_fail_once(const char *func, const char *caller)
{
- char *p;
+ char *p, *location = make_location(func, caller);
struct fail_decision *i;
if (failpath) {
if (streq(location, i->location))
return false;
- if (should_i_fail(location)) {
+ if (should_i_fail(func, caller)) {
excessive_fails++;
return true;
}
}
/* Should I fail at this point? */
-bool should_i_fail(const char *func)
+bool should_i_fail(const char *func, const char *caller)
{
pid_t child;
int status, pfd[2];
struct fail_decision *dec;
size_t log_size;
char *log;
+ char *location = make_location(func, caller);
if (failpath)
- return do_failpath(func);
+ return do_failpath(location);
failpoints++;
if (!failtest)
}
dec = talloc(NULL, struct fail_decision);
- dec->location = talloc_strdup(dec, func);
+ dec->location = talloc_steal(dec, location);
dec->tui_line = tui_linenum;
DLIST_ADD_END(decisions, dec, struct fail_decision);