Exemplo n.º 1
0
	/**
	 *
     * This entry point is tailored for the Watchdog module.
     * Since the thread to be traced may be running, it requires a ThreadControls object in order to suspend/resume the thread.
     * @brief RemoteStacktrace
     */
    void SuspendedStacktrace(Threading::ThreadControls* ctls, const std::string& threadName)
    {
#if !(DEDICATED || UNIT_TEST)
        Watchdog::ClearTimer();
#endif
        assert(ctls != nullptr);
        assert(ctls->handle != 0);
        assert(threadName.size() > 0);

        LOG_L(L_WARNING, "Suspended-thread Stacktrace (%s) for Spring %s:", threadName.c_str(), (SpringVersion::GetFull()).c_str());

        LOG_L(L_DEBUG, "SuspendedStacktrace[1]");

        StackTrace stacktrace;

        // Get untranslated stacktrace symbols
        {
            // process and analyse the raw stack trace
            void* iparray[MAX_STACKTRACE_DEPTH];

			ctls->Suspend();

			const int numLines = thread_unwind(&ctls->ucontext, iparray, stacktrace);

			ctls->Resume();

            LOG_L(L_DEBUG, "SuspendedStacktrace[2]");

            if(numLines > MAX_STACKTRACE_DEPTH) {
                LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
            }
            char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

            ExtractSymbols(lines, stacktrace);
        }

        if (stacktrace.empty()) {
            LOG_L(L_WARNING, "  Unable to create suspended stacktrace");
            return;
        }

        LOG_L(L_DEBUG, "SuspendedStacktrace[3]");

        // Translate symbols into code line numbers
        TranslateStackTrace(NULL, stacktrace, LOG_LEVEL_WARNING);

        LOG_L(L_DEBUG, "SuspendedStacktrace[4]");

        // Print out the translated StackTrace
        LogStacktrace(LOG_LEVEL_WARNING, stacktrace);

    }
Exemplo n.º 2
0
    /**
     * This stack trace is tailored for the SIGSEGV / SIGILL / SIGFPE etc signal handler.
     * The thread to be traced is usually in a halted state, but the signal handler can provide siginfo_t and ucontext_t structures to help produce the trace using libunwind.
     * @brief PrepareStacktrace
     */
    void HaltedStacktrace(const std::string& errstr, siginfo_t* siginfo, ucontext_t* ucontext)
    {
        LOG_L(L_ERROR, "Halted Stacktrace for Spring %s using libunwind:", (SpringVersion::GetFull()).c_str());

        assert(siginfo != nullptr);
        assert(ucontext != nullptr);

        StackTrace stacktrace;

        LOG_L(L_DEBUG, "HaltedStacktrace[1]");

        // Get untranslated stacktrace symbols
        {
            // process and analyse the raw stack trace
            void* iparray[MAX_STACKTRACE_DEPTH];

            const int numLines = thread_unwind(nullptr, iparray, stacktrace);

            LOG_L(L_DEBUG, "HaltedStacktrace[2]");

            if(numLines > MAX_STACKTRACE_DEPTH) {
                LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
            }

            char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

            ExtractSymbols(lines, stacktrace);
        }

        LOG_L(L_DEBUG, "HaltedStacktrace[3]");

        if (stacktrace.empty()) {
            LOG_I(LOG_LEVEL_ERROR, "  Unable to create stacktrace");
            return;
        }

        // Translate it
        TranslateStackTrace(NULL, stacktrace, LOG_LEVEL_ERROR);

        LOG_L(L_DEBUG, "HaltedStacktrace[4]");

        // Print out the translated StackTrace. Ignore the frames that occur inside the signal handler (before its line in the trace) -- they are likely some kind of padding or just garbage.
        LogStacktrace(LOG_LEVEL_ERROR, stacktrace);
    }
Exemplo n.º 3
0
	static void Stacktrace(bool* aiCrash, pthread_t* hThread = NULL, const char* threadName = NULL, const int logLevel = LOG_LEVEL_ERROR)
	{
#if !(DEDICATED || UNIT_TEST)
		Watchdog::ClearTimer();
#endif

		if (threadName != NULL) {
			LOG_I(logLevel, "Stacktrace (%s) for Spring %s:", threadName, (SpringVersion::GetFull()).c_str());
		} else {
			LOG_I(logLevel, "Stacktrace for Spring %s:", (SpringVersion::GetFull()).c_str());
		}

		StackTrace stacktrace;

		// Get untranslated stacktrace symbols
		{
			// process and analyse the raw stack trace
			void* iparray[MAX_STACKTRACE_DEPTH];
			int numLines = thread_unwind(nullptr, iparray, stacktrace);
			if (numLines > MAX_STACKTRACE_DEPTH) {
				LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
			}
			char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

			ExtractSymbols(lines, stacktrace);
		}

		if (stacktrace.empty()) {
			LOG_I(logLevel, "  Unable to create stacktrace");
			return;
		}

		// Translate it
		TranslateStackTrace(aiCrash, stacktrace, logLevel);

		LogStacktrace(logLevel, stacktrace);
	}
Exemplo n.º 4
0
void
_pthread_exit_mask(void *status, sigset_t *mask)
{
    struct pthread *curthread = _get_curthread();

    /* Check if this thread is already in the process of exiting: */
    if (curthread->cancelling) {
        char msg[128];
        snprintf(msg, sizeof(msg), "Thread %p has called "
                 "pthread_exit() from a destructor. POSIX 1003.1 "
                 "1996 s16.2.5.2 does not allow this!", curthread);
        PANIC(msg);
    }

    /* Flag this thread as exiting. */
    curthread->cancelling = 1;
    curthread->no_cancel = 1;
    curthread->cancel_async = 0;
    curthread->cancel_point = 0;
    if (mask != NULL)
        __sys_sigprocmask(SIG_SETMASK, mask, NULL);
    if (curthread->unblock_sigcancel) {
        sigset_t set;

        curthread->unblock_sigcancel = 0;
        SIGEMPTYSET(set);
        SIGADDSET(set, SIGCANCEL);
        __sys_sigprocmask(SIG_UNBLOCK, mask, NULL);
    }

    /* Save the return value: */
    curthread->ret = status;
#ifdef _PTHREAD_FORCED_UNWIND

#ifdef PIC
    thread_uw_init();
#endif /* PIC */

#ifdef PIC
    if (uwl_forcedunwind != NULL) {
#else
    if (_Unwind_ForcedUnwind != NULL) {
#endif
        if (curthread->unwind_disabled) {
            if (message_printed == 0) {
                message_printed = 1;
                _thread_printf(2, "Warning: old _pthread_cleanup_push was called, "
                               "stack unwinding is disabled.\n");
            }
            goto cleanup;
        }
        thread_unwind();

    } else {
cleanup:
        while (curthread->cleanup != NULL) {
            __pthread_cleanup_pop_imp(1);
        }
        exit_thread();
    }

#else
    while (curthread->cleanup != NULL) {
        __pthread_cleanup_pop_imp(1);
    }

    exit_thread();
#endif /* _PTHREAD_FORCED_UNWIND */
}

static void
exit_thread(void)
{
    struct pthread *curthread = _get_curthread();

    /* Check if there is thread specific data: */
    if (curthread->specific != NULL) {
        /* Run the thread-specific data destructors: */
        _thread_cleanupspecific();
    }

    if (!_thr_isthreaded())
        exit(0);

    if (atomic_fetchadd_int(&_thread_active_threads, -1) == 1) {
        exit(0);
        /* Never reach! */
    }

    /* Tell malloc that the thread is exiting. */
    _malloc_thread_cleanup();

    THR_LOCK(curthread);
    curthread->state = PS_DEAD;
    if (curthread->flags & THR_FLAGS_NEED_SUSPEND) {
        curthread->cycle++;
        _thr_umtx_wake(&curthread->cycle, INT_MAX, 0);
    }
    if (!curthread->force_exit && SHOULD_REPORT_EVENT(curthread, TD_DEATH))
        _thr_report_death(curthread);
    /*
     * Thread was created with initial refcount 1, we drop the
     * reference count to allow it to be garbage collected.
     */
    curthread->refcount--;
    _thr_try_gc(curthread, curthread); /* thread lock released */

#if defined(_PTHREADS_INVARIANTS)
    if (THR_IN_CRITICAL(curthread))
        PANIC("thread exits with resources held!");
#endif
    /*
     * Kernel will do wakeup at the address, so joiner thread
     * will be resumed if it is sleeping at the address.
     */
    thr_exit(&curthread->tid);
    PANIC("thr_exit() returned");
    /* Never reach! */
}