Repository: dotnet/runtime
File: src/coreclr/vm/threads.cpp (C++)

Code before:
    Thread* origThread = t_CurrentThreadInfo.m_pThread;
    t_CurrentThreadInfo.m_pThread = t;
    if (t != NULL)
    {
        _ASSERTE(origThread == NULL);
        InitializeCurrentThreadsStaticData(t);
        EnsureTlsDestructionMonitor();
        t->InitRuntimeThreadLocals();
    }
#ifdef TARGET_WINDOWS
    else if (origThread != NULL)
    {
        // Unregister from OS notifications
        // This can return false if a thread did not register for OS notification.
        OsDetachThread(origThread);
    }
#endif

    // Clear or set the app domain to the one domain based on if the thread is being nulled out or set
    if (t != NULL)
    {
        t_CurrentThreadInfo.m_pAppDomain = AppDomain::GetCurrentDomain();
#if defined(TARGET_UNIX) && !defined(TARGET_WASM)
        if (!InsertThreadIntoAsyncSafeMap(t->GetOSThreadId64(), t))
        {
            // TODO: can we handle this OOM more gracefully?
            EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to insert thread into async-safe map due to OOM."));
        }
#endif // TARGET_UNIX && !TARGET_WASM
    }
    else
    {
        t_CurrentThreadInfo.m_pAppDomain = NULL;
#if defined(TARGET_UNIX) && !defined(TARGET_WASM)
        if (origThread != NULL)
        {
            RemoveThreadFromAsyncSafeMap(origThread->GetOSThreadId64(), origThread);
        }
#endif // TARGET_UNIX && !TARGET_WASM
    }
}

BOOL Thread::Alert ()
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    BOOL fRetVal = FALSE;

Review comment (bug):
We can - if it is one of our threads. However, I do not think it is worth it. The allocation of the thread statics above can crash due to OOM too and I do not think there is a good way to recover from it either. Recovering from corner-case OOMs is just not a thing on Unix.

Code after:
    Thread* origThread = t_CurrentThreadInfo.m_pThread;
    t_CurrentThreadInfo.m_pThread = t;
    if (t != NULL)
    {
        _ASSERTE(origThread == NULL);
        InitializeCurrentThreadsStaticData(t);
        EnsureTlsDestructionMonitor();
        t->InitRuntimeThreadLocals();
    }
#ifdef TARGET_WINDOWS
    else if (origThread != NULL)
    {
        // Unregister from OS notifications
        // This can return false if a thread did not register for OS notification.
        OsDetachThread(origThread);
    }
#endif

    // Clear or set the app domain to the one domain based on if the thread is being nulled out or set
    if (t != NULL)
    {
        t_CurrentThreadInfo.m_pAppDomain = AppDomain::GetCurrentDomain();
#if defined(TARGET_UNIX) && !defined(TARGET_WASM)
        if (!InsertThreadIntoAsyncSafeMap(t->GetOSThreadId64(), t))
        {
            EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to insert thread into async-safe map due to out of memory."));
        }
#endif // TARGET_UNIX && !TARGET_WASM
    }
    else
    {
        t_CurrentThreadInfo.m_pAppDomain = NULL;
#if defined(TARGET_UNIX) && !defined(TARGET_WASM)
        if (origThread != NULL)
        {
            RemoveThreadFromAsyncSafeMap(origThread->GetOSThreadId64(), origThread);
        }
#endif // TARGET_UNIX && !TARGET_WASM
    }
}

BOOL Thread::Alert ()
{
    CONTRACTL {
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    BOOL fRetVal = FALSE;
    {