Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3864aa39 authored by Kenny Root's avatar Kenny Root Committed by Gerrit Code Review
Browse files

Merge "Add interrupter library to simulate EINTR"

parents 6b96e2f0 0054cbd4
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    interrupter.c
LOCAL_MODULE := interrupter
LOCAL_MODULE_TAGS := eng tests
LOCAL_LDFLAGS := -ldl

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    interrupter.c
LOCAL_MODULE := interrupter
LOCAL_MODULE_TAGS := eng tests
LOCAL_LDFLAGS := -ldl

include $(BUILD_HOST_SHARED_LIBRARY)
 No newline at end of file
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright 2012, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * The probability of a syscall failing from 0.0 to 1.0
 */
#define PROBABILITY 0.9



#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

/* for various intercepted calls */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>

/* For builds on glibc */
#define __USE_GNU
#include <dlfcn.h>

#include "interrupter.h"

static int probability = PROBABILITY * RAND_MAX;

static int maybe_interrupt() {
    if (rand() < probability) {
        return 1;
    }
    return 0;
}

DEFINE_INTERCEPT(read, ssize_t, int, void*, size_t);
DEFINE_INTERCEPT(write, ssize_t, int, const void*, size_t);
DEFINE_INTERCEPT(accept, int, int, struct sockaddr*, socklen_t*);
DEFINE_INTERCEPT(creat, int, const char*, mode_t);
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright 2012, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2)  arg1##arg2

#define INTERRUPTER(sym) \
    if (real_##sym == NULL) \
        __init_##sym(); \
    if (maybe_interrupt()) { \
        errno = EINTR; \
        return -1; \
    }

#define CALL_FUNCTION_1(sym, ret, type1) \
ret (*real_##sym)(type1) = NULL; \
ret sym(type1 arg1) { \
    INTERRUPTER(sym) \
    return real_##sym(arg1); \
}

#define CALL_FUNCTION_2(sym, ret, type1, type2) \
ret (*real_##sym)(type1, type2) = NULL; \
ret sym(type1 arg1, type2 arg2) { \
    INTERRUPTER(sym) \
    return real_##sym(arg1, arg2); \
}

#define CALL_FUNCTION_3(sym, ret, type1, type2, type3) \
ret (*real_##sym)(type1, type2, type3) = NULL; \
ret sym(type1 arg1, type2 arg2, type3 arg3) { \
    INTERRUPTER(sym) \
    return real_##sym(arg1, arg2, arg3); \
}

#define CALL_FUNCTION_4(sym, ret, type1, type2, type3, type4) \
ret (*real_##sym)(type1, type2, type3, type4) = NULL; \
ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
    INTERRUPTER(sym) \
    return real_##sym(arg1, arg2, arg3, arg4); \
}

#define CALL_FUNCTION_5(sym, ret, type1, type2, type3, type4, type5) \
ret (*real_##sym)(type1, type2, type3, type4, type5) = NULL; \
ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
    INTERRUPTER(sym) \
    return real_##sym(arg1, arg2, arg3, arg4, arg5); \
}

#define DEFINE_INTERCEPT_N(N, sym, ret, ...) \
static void __init_##sym(void); \
CONCATENATE(CALL_FUNCTION_, N)(sym, ret, __VA_ARGS__) \
static void __init_##sym(void) { \
    real_##sym = dlsym(RTLD_NEXT, #sym); \
    if (real_##sym == NULL) { \
        fprintf(stderr, "Error hooking " #sym ": %s\n", dlerror()); \
    } \
}

#define INTERCEPT_NARG(...) INTERCEPT_NARG_N(__VA_ARGS__, INTERCEPT_RSEQ_N())
#define INTERCEPT_NARG_N(...) INTERCEPT_ARG_N(__VA_ARGS__)
#define INTERCEPT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define INTERCEPT_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0

#define DEFINE_INTERCEPT(sym, ret, ...) DEFINE_INTERCEPT_N(INTERCEPT_NARG(__VA_ARGS__), sym, ret, __VA_ARGS__)