Repository: SerenityOS/serenity
File: Kernel/Tasks/Process.cpp (C++)

Code before:
}

void Process::remove_from_secondary_lists()
{
    m_scoped_process_list.with([this](auto& list_ptr) {
        if (list_ptr) {
            list_ptr->attached_processes().with([&](auto& list) {
                list.remove(*this);
            });
            list_ptr->detach({});
        }
    });
}

void Process::die()
{
    auto expected = State::Running;
    if (!m_state.compare_exchange_strong(expected, State::Dying, AK::memory_order_acquire)) {
        // It's possible that another thread calls this at almost the same time
        // as we can't always instantly kill other threads (they may be blocked)
        // So if we already were called then other threads should stop running
        // momentarily and we only really need to service the first thread
        return;
    }

    {
        SpinlockLocker lock(g_scheduler_lock);
        set_stopped(false);
    }
    // Let go of the TTY, otherwise a slave PTY may keep the master PTY from
    // getting an EOF when the last process using the slave PTY dies.
    // If the master PTY owner relies on an EOF to know when to wait() on a
    // slave owner, we have to allow the PTY pair to be torn down.
    with_mutable_protected_data([&](auto& protected_data) { protected_data.tty = nullptr; });

    VERIFY(m_threads_for_coredump.is_empty());
    for_each_thread([&](auto& thread) {
        auto result = m_threads_for_coredump.try_append(thread);
        if (result.is_error())
            dbgln("Failed to add thread {} to coredump due to OOM", thread.tid());
    });

    all_instances().with([&](auto const& list) {
        for (auto it = list.begin(); it != list.end();) {
            auto& process = *it;
            ++it;
            if (process.has_tracee_thread(pid())) {
                if constexpr (PROCESS_DEBUG) {
                    process.name().with([&](auto& process_name) {
                        name().with([&](auto& name) {
                            dbgln("Process {} ({}) is attached by {} ({}) which will exit", process_name.representable_view(), process.pid(), name.representable_view(), pid());

Review comment (suggestion):
I'd remove the extra scoping for this and just hold the lock until the end of the function. `set_stopped` is already an atomic operation, so the idea with taking this lock is just to prevent a concurrent `Thread::set_state` from changing the process's stopped state before its threads are marked to die.

Code after:
}

void Process::remove_from_secondary_lists()
{
    m_scoped_process_list.with([this](auto& list_ptr) {
        if (list_ptr) {
            list_ptr->attached_processes().with([&](auto& list) {
                list.remove(*this);
            });
            list_ptr->detach({});
        }
    });
}

void Process::die()
{
    auto expected = State::Running;
    if (!m_state.compare_exchange_strong(expected, State::Dying, AK::memory_order_acquire)) {
        // It's possible that another thread calls this at almost the same time
        // as we can't always instantly kill other threads (they may be blocked)
        // So if we already were called then other threads should stop running
        // momentarily and we only really need to service the first thread
        return;
    }

    {
        SpinlockLocker lock(g_scheduler_lock);
        set_stopped(false);

        // Let go of the TTY, otherwise a slave PTY may keep the master PTY from
        // getting an EOF when the last process using the slave PTY dies.
        // If the master PTY owner relies on an EOF to know when to wait() on a
        // slave owner, we have to allow the PTY pair to be torn down.
        with_mutable_protected_data([&](auto& protected_data) { protected_data.tty = nullptr; });

        VERIFY(m_threads_for_coredump.is_empty());
        for_each_thread([&](auto& thread) {
            auto result = m_threads_for_coredump.try_append(thread);
            if (result.is_error())
                dbgln("Failed to add thread {} to coredump due to OOM", thread.tid());
        });

        kill_all_threads();
    }

    all_instances().with([&](auto const& list) {
        for (auto it = list.begin(); it != list.end();) {
            auto& process = *it;
            ++it;
            if (process.has_tracee_thread(pid())) {
                if constexpr (PROCESS_DEBUG) {