Windows 10 конкретный сбой при вызове LeaveCriticalSection
Я застрял в проблеме с синхронизацией потоков и критических разделов в Windows 10.
Приложение будет зависать в этом случае:
Приложение имеет две темы.Поток 1 вызывает EnterCriticalSection с объектом m_CSЗатем поток 2 пытается войти в тот же критический разделПоток 1 завершает поток 2, используя TerminateThreadПоток 1 вызывает LeaveCriticalSectionВ предыдущих версиях Windows, которые я смог протестировать (7, 8, 8.1), это работает правильно. Поток 2 завершается, а Поток 1 покидает критическую секцию без исключения.
В Windows 10, когда поток 1 покидает критическую секцию, происходит сбой приложения с нарушением прав доступа. Это происходит только тогда, когда другой поток был прерван во время ожидания на EnterCriticalThread.
Если посмотреть на трассировку стека, это выглядит так (последний кадр вверху):
RtlpWakeByAddress
RtlpUnWaitCriticalSection
RtlLeaveCriticalSection
Я потратил так много времени на отладку этой проблемы. В моем случае с m_CS все в порядке, когда вызывается LeaveCriticalSection. Я отладил и потратил некоторое время на анализ разобранного кода функций ntdll.dll. Похоже, объект повреждается где-то во время выполнения RtlpUnWaitCriticalSection и затем передается в RtlpWakeByAddress при возникновении сбоя. В основном ntdll.dll был в состоянии изменить свойства объекта CRITICAL_SECTION, такие как счетчик блокировок в RtlLeaveCriticalSection.
Из Интернета я не нашел ни одного ответа на это или утверждение, что изменилось в Windows 10. Только поток в reddit и ~ 1800 отчетов о сбоях для Mozilla Firefox с тем же стеком вызовов в прошлом месяце. Я связался с автором поста на Reddit, и он до сих пор не смог это исправить.
Так кто-нибудь имел дело с этой проблемой и может быть есть решение или советы? В качестве решения прямо сейчас я вижу только переосмысление использования WinAPI TerminateThread и стараюсь максимально избегать его. Другой способ, вероятно, сделать рефакторинг кода и подумать об архитектуре приложения.
Любой ответ приветствуется. заранее спасибо