Beispiel #1
0
static
int handshake_with_thread()
{
    udi_errmsg errmsg;
    errmsg.size = ERRMSG_SIZE;
    errmsg.msg[ERRMSG_SIZE-1] = '\0';

    unsigned char trigger = 0;
    if ( read(thread_barrier.read_handle, &trigger, 1) != 1 ) {
        udi_log("failed to read trigger from pipe: %e", errno);
        return RESULT_ERROR;
    }

    if ( trigger != sentinel ) {
        udi_abort();
        return RESULT_ERROR;
    }

    thread *request_thr = NULL;
    int result = wait_and_execute_command(&errmsg, &request_thr);
    if (result == RESULT_ERROR) {
        udi_log("failed to handle command after thread create");
        udi_abort();
    }

    release_other_threads();

    return result;
}
Beispiel #2
0
static
void report_thread_death() {

    // block signals while reporting the thread death
    sigset_t block_set;
    sigset_t original_set;
    sigfillset(&block_set);

    if (setsigmask(SIG_SETMASK, &block_set, &original_set) == -1) {
        udi_abort();
    }

    udi_log("thread %a dying", get_user_thread_id());

    thread *thr = get_current_thread();
    thr->stack_event_pending = 1;

    int block_result = block_other_threads();
    if (block_result < 0) {
        udi_log("failed to block other threads");
        udi_abort();
        return;
    }

    if (block_result > 0) {
        // the thread should always eventually be the control thread
        udi_abort();
    } else {
        thr->stack_event_pending = 0;

        int death_result = handle_thread_death();
        if (death_result != RESULT_SUCCESS) {
            udi_log("failed to handle thread death");
            udi_abort();
            return;
        }

        udi_errmsg errmsg;
        errmsg.size = ERRMSG_SIZE;
        errmsg.msg[ERRMSG_SIZE-1] = '\0';
        thread *request_thr = NULL;

        int request_result = wait_and_execute_command(&errmsg, &request_thr);
        if (request_result == RESULT_ERROR) {
            udi_log("failed to handle command after thread death");
            udi_abort();
        }

        release_other_threads();
    }

    setsigmask(SIG_SETMASK, &original_set, NULL);
}
Beispiel #3
0
/**
 * Gets the specified register from the context
 *
 * @param reg the register to retrieve
 * @param context the context
 *
 * @return the value from the register
 */
unsigned long get_register_ud_type(ud_type_t reg, const void *context) {
    const ucontext_t *u_context = (const ucontext_t *)context;

    int offset = get_reg_context_offset(reg);

    if ( offset == -1 ) {
        udi_abort(__FILE__, __LINE__);
    }

    return u_context->uc_mcontext.gregs[offset];
}
Beispiel #4
0
int pthread_create(pthread_t *thread,
                   const pthread_attr_t *attr,
                   void *(*start_routine)(void *),
                   void *arg)
{
    udi_log("thread %a creating a new thread", get_user_thread_id());

    int block_result = block_other_threads();
    if (block_result < 0) {
        udi_log("failed to block other threads");
        udi_abort();
        return ENOMEM;
    }

    struct wrapped_thread_context *context =
        (struct wrapped_thread_context *)udi_malloc(sizeof(struct wrapped_thread_context));
    context->start_routine = start_routine;
    context->arg = arg;
    context->creator_tid = get_user_thread_id();

    int control_pipe[2];
    if ( init_control_pipe(control_pipe) != 0 ) {
        return ENOMEM;
    }

    int create_result = real_pthread_create(thread, attr, wrapped_start_routine, context);
    if (create_result == 0) {
        int handshake_result = handshake_with_thread();
        if (handshake_result != RESULT_SUCCESS) {
            return ENOMEM;
        }
    } else {
        if (get_multithread_capable()) {
            close(control_pipe[0]);
            close(control_pipe[1]);
        }
    }
    return create_result;
}
Beispiel #5
0
static
void *wrapped_start_routine(void *arg)
{
    struct wrapped_thread_context *context = (struct wrapped_thread_context *)arg;

    void *ret_value = NULL;
    do {
        int create_result = handle_thread_create(context->creator_tid);

        if (create_result != RESULT_SUCCESS) {
            udi_log("failed to handle thread creation");
            udi_abort();
            break;
        }
        ret_value = context->start_routine(context->arg);

        report_thread_death();
    }while(0);

    udi_free(context);

    return ret_value;
}
Beispiel #6
0
static
int handle_thread_create(uint64_t creator_thr)
{
    int result;
    uint64_t tid;

    udi_errmsg errmsg;
    errmsg.size = ERRMSG_SIZE;
    errmsg.msg[ERRMSG_SIZE-1] = '\0';

    do {
        tid = get_user_thread_id();
        udi_log("thread create event for %a", tid);

        thread *thr = create_thread(tid);
        if (thr == NULL) {
            result = RESULT_ERROR;
            break;
        }

        if ( thread_create_callback(thr, &errmsg) != 0 ) {
            result = RESULT_ERROR;
            break;
        }

        result = handle_thread_create_event(creator_thr, tid, &errmsg);
        if (result != RESULT_SUCCESS) {
            break;
        }

        result = thread_create_handshake(thr, &errmsg);
        if (result != RESULT_SUCCESS) {
            break;
        }

        if ( write(thread_barrier.write_handle, &sentinel, 1) != 1 ) {
            udi_log("failed to write trigger to pipe: %e", errno);
            result = RESULT_ERROR;
            break;
        }

        unsigned char trigger = 0;
        while (trigger == 0) {
            int trigger_read_result = read(thr->control_read, &trigger, 1);
            if (trigger_read_result == -1) {
                if (errno == EINTR) {
                    continue;
                }
                udi_log("failed to read control trigger from pipe: %e", errno);
                result = RESULT_ERROR;
                break;
            }
            result = RESULT_SUCCESS;
        }
        if (result != RESULT_SUCCESS) {
            break;
        }

        if ( trigger != sentinel ) {
            udi_abort();
        }
    }while(0);

    if ( result != RESULT_SUCCESS ) {
        udi_log("failed to report thread create of %a: %s",
                tid,
                errmsg.msg);
    }

    return result;
}