Beispiel #1
0
static void
faulthandler_thread(void *unused)
{
    PyLockStatus st;
    const char* errmsg;
    PyThreadState *current;
    int ok;

    do {
        st = PyThread_acquire_lock_timed(thread.cancel_event,
                                         thread.timeout_ms, 0);
        if (st == PY_LOCK_ACQUIRED) {
            /* Cancelled by user */
            break;
        }
        /* Timeout => dump traceback */
        assert(st == PY_LOCK_FAILURE);

        /* get the thread holding the GIL, NULL if no thread hold the GIL */
        current = _Py_atomic_load_relaxed(&_PyThreadState_Current);

        errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current);
        ok = (errmsg == NULL);

        if (thread.exit)
            _exit(1);
    } while (ok && thread.repeat);

    /* The only way out */
    PyThread_release_lock(thread.cancel_event);
    PyThread_release_lock(thread.join_event);
}
Beispiel #2
0
/* Keep this as a static, as it is not reliable!  It can only
   ever be compared to the state for the *current* thread.
   * If not equal, then it doesn't matter that the actual
     value may change immediately after comparison, as it can't
     possibly change to the current thread's state.
   * If equal, then the current thread holds the lock, so the value can't
     change until we yield the lock.
*/
static int
PyThreadState_IsCurrent(PyThreadState *tstate)
{
    /* Must be the tstate for this thread */
    assert(PyGILState_GetThisThreadState()==tstate);
    return tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
}
Beispiel #3
0
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
    PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
        &_PyThreadState_Current);

    _Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
    /* It should not be possible for more than one thread state
       to be used for a thread.  Check this the best we can in debug
       builds.
    */
#if defined(Py_DEBUG) && defined(WITH_THREAD)
    if (newts) {
        /* This can be called from PyEval_RestoreThread(). Similar
           to it, we need to ensure errno doesn't change.
        */
        int err = errno;
        PyThreadState *check = PyGILState_GetThisThreadState();
        if (check && check->interp == newts->interp && check != newts)
            Py_FatalError("Invalid thread state for this thread");
        errno = err;
    }
#endif
    return oldts;
}
Beispiel #4
0
int
PyGILState_Check(void)
{
    /* can't use PyThreadState_Get() since it will assert that it has the GIL */
    PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
        &_PyThreadState_Current);
    return tstate && (tstate == PyGILState_GetThisThreadState());
}
Beispiel #5
0
PyThreadState *
PyThreadState_Get(void)
{
    PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
        &_PyThreadState_Current);
    if (tstate == NULL)
        Py_FatalError("PyThreadState_Get: no current thread");

    return tstate;
}
Beispiel #6
0
void
PyThreadState_Delete(PyThreadState *tstate)
{
    if (tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
        Py_FatalError("PyThreadState_Delete: tstate is still current");
#ifdef WITH_THREAD
    if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
        PyThread_delete_key_value(autoTLSkey);
#endif /* WITH_THREAD */
    tstate_delete_common(tstate);
}
Beispiel #7
0
PyObject *
PyErr_Occurred(void)
{
    /* If there is no thread state, PyThreadState_GET calls
       Py_FatalError, which calls PyErr_Occurred.  To avoid the
       resulting infinite loop, we inline PyThreadState_GET here and
       treat no thread as no error. */
    PyThreadState *tstate =
        ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current));

    return tstate == NULL ? NULL : tstate->curexc_type;
}
Beispiel #8
0
void
PyThreadState_DeleteCurrent()
{
    PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
        &_PyThreadState_Current);
    if (tstate == NULL)
        Py_FatalError(
            "PyThreadState_DeleteCurrent: no current tstate");
    _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
    if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
        PyThread_delete_key_value(autoTLSkey);
    tstate_delete_common(tstate);
    PyEval_ReleaseLock();
}
Beispiel #9
0
PyObject *
PyThreadState_GetDict(void)
{
    PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
        &_PyThreadState_Current);
    if (tstate == NULL)
        return NULL;

    if (tstate->dict == NULL) {
        PyObject *d;
        tstate->dict = d = PyDict_New();
        if (d == NULL)
            PyErr_Clear();
    }
    return tstate->dict;
}
Beispiel #10
0
void
Py_FatalError(const char *msg)
{
    const int fd = fileno(stderr);
    PyThreadState *tstate;

    fprintf(stderr, "Fatal Python error: %s\n", msg);
    fflush(stderr); /* it helps in Windows debug build */
    if (PyErr_Occurred()) {
        PyErr_PrintEx(0);
    }
    else {
        tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
        if (tstate != NULL) {
            fputc('\n', stderr);
            fflush(stderr);
            _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
        }
        _PyFaulthandler_Fini();
    }

#ifdef MS_WINDOWS
    {
        size_t len = strlen(msg);
        WCHAR* buffer;
        size_t i;

        /* Convert the message to wchar_t. This uses a simple one-to-one
        conversion, assuming that the this error message actually uses ASCII
        only. If this ceases to be true, we will have to convert. */
        buffer = alloca( (len+1) * (sizeof *buffer));
        for( i=0; i<=len; ++i)
            buffer[i] = msg[i];
        OutputDebugStringW(L"Fatal Python error: ");
        OutputDebugStringW(buffer);
        OutputDebugStringW(L"\n");
    }
#ifdef _DEBUG
    DebugBreak();
#endif
#endif /* MS_WINDOWS */
    abort();
}
Beispiel #11
0
static void
faulthandler_thread(void *unused)
{
    PyLockStatus st;
    const char* errmsg;
    PyThreadState *current;
    int ok;
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
    sigset_t set;

    /* we don't want to receive any signal */
    sigfillset(&set);
    pthread_sigmask(SIG_SETMASK, &set, NULL);
#endif

    do {
        st = PyThread_acquire_lock_timed(thread.cancel_event,
                                         thread.timeout_us, 0);
        if (st == PY_LOCK_ACQUIRED) {
            PyThread_release_lock(thread.cancel_event);
            break;
        }
        /* Timeout => dump traceback */
        assert(st == PY_LOCK_FAILURE);

        /* get the thread holding the GIL, NULL if no thread hold the GIL */
        current = _Py_atomic_load_relaxed(&_PyThreadState_Current);

        write(thread.fd, thread.header, thread.header_len);

        errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current);
        ok = (errmsg == NULL);

        if (thread.exit)
            _exit(1);
    } while (ok && thread.repeat);

    /* The only way out */
    PyThread_release_lock(thread.running);
}