Skip to content

Unable to attach to thread that is blocking SIGILL #7805

@jackgallagher-arm

Description

@jackgallagher-arm

Perhaps this is a more of a known limitation than a bug but I have come across an application in the wild that has a thread which blocks all signals using pthread_sigmask() then handles signals by calling sigwaitinfo() in a loop.

When statically linking DynamoRIO into the app we are unable to take over the signal handling thread because SIGILL is blocked.

We are able to work around it by modifying the app to unblock SIGILL but perhaps there is a way for DynamoRIO to unblock SIGILL before attempting to attach (perhaps using ptrace if it is not possible using regular APIs).

Here is a test app that reproduces the issue:

#include "configure.h"
#include "dr_api.h"
#include "tools.h"
#include "condvar.h"
#include "thread.h"

#include <errno.h>
#include <signal.h>

#ifndef UNIX
#    error UNIX-only
#endif

static void *signals_blocked;

static THREAD_FUNC_RETURN_TYPE
sig_thread(void *arg)
{
    sigset_t set;
    siginfo_t info;
    int res;

    sigfillset(&set);
    res = pthread_sigmask(SIG_BLOCK, &set, NULL);
    assert(res == 0);

    print("sig_thread blocked signals\n");
    signal_cond_var(signals_blocked);

    while (true) {
        res = sigwaitinfo(&set, &info);
        if (res == -1) {
            if (errno == EINTR)
                continue;
        }
        assert(res != -1);
        if (res == SIGUSR1) {
            print("sig_thread received SIGUSR1\n");
            break;
        }
    }
    return NULL;
}

DR_EXPORT void
dr_client_main(client_id_t id, int argc, const char *argv[])
{
    print("in dr_client_main\n");
}

int
main(int argc, const char *argv[])
{
    signals_blocked = create_cond_var();

    print("starting sig_thread\n");
    thread_t thread = create_thread(sig_thread, NULL);

    wait_cond_var(signals_blocked);

    print("pre-DR start\n");
    assert(!dr_app_running_under_dynamorio());
    dr_app_setup_and_start(); /* This call will hang because we can't attach to sig_thread. */
    assert(dr_app_running_under_dynamorio());

    print("sending SIGUSR1 to sig_thread\n");
    pthread_kill(thread, SIGUSR1);
    join_thread(thread);

    print("pre-DR stop\n");
    dr_app_stop_and_cleanup();
    assert(!dr_app_running_under_dynamorio());

    destroy_cond_var(signals_blocked);

    print("all done\n");
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions