From c7a133ac9cffa6c1d3756f6f317635f711b7da15 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 31 Oct 2022 14:05:22 -0300 Subject: [PATCH] windivert: avoid trying to send during shutdown Occasionally during shutdown windivert will crash because a thread tries sending after we've called wd::shutdown, which isn't allowed. Add an atomic bool to prevent this. --- llarp/win32/windivert.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/llarp/win32/windivert.cpp b/llarp/win32/windivert.cpp index 02a799bc7..344718db1 100644 --- a/llarp/win32/windivert.cpp +++ b/llarp/win32/windivert.cpp @@ -61,6 +61,7 @@ namespace llarp::win32 HANDLE m_Handle; std::thread m_Runner; + std::atomic m_Shutdown{false}; thread::Queue m_RecvQueue; // dns packet queue size static constexpr size_t recv_queue_size = 64; @@ -93,6 +94,7 @@ namespace llarp::win32 { auto err = GetLastError(); if (err == ERROR_NO_DATA) + // The handle is shut down and the packet queue is empty return std::nullopt; if (err == ERROR_BROKEN_PIPE) { @@ -116,9 +118,8 @@ namespace llarp::win32 const auto* addr = &w_pkt.addr; log::trace(logcat, "send dns packet of size {}B", pkt.size()); UINT sz{}; - if (wd::send(m_Handle, pkt.data(), pkt.size(), &sz, addr)) - return; - throw win32::error{"windivert send failed"}; + if (!wd::send(m_Handle, pkt.data(), pkt.size(), &sz, addr)) + throw win32::error{"windivert send failed"}; } virtual int @@ -141,7 +142,8 @@ namespace llarp::win32 return net::IPPacket{}; net::IPPacket pkt{std::move(w_pkt->pkt)}; pkt.reply = [this, addr = std::move(w_pkt->addr)](auto pkt) { - send_packet(Packet{pkt.steal(), addr}); + if (!m_Shutdown) + send_packet(Packet{pkt.steal(), addr}); }; return pkt; } @@ -178,6 +180,7 @@ namespace llarp::win32 Stop() override { log::info(logcat, "stopping windivert"); + m_Shutdown = true; wd::shutdown(m_Handle, WINDIVERT_SHUTDOWN_BOTH); m_Runner.join(); }