2 pontos por GN⁺ 2024-03-04 | 1 comentários | Compartilhar no WhatsApp

Possível bug em std::shared_mutex no Windows

  • Uma equipe de software encontrou um comportamento inesperado relacionado a std::shared_mutex no Windows.
  • Esse problema ocorre apenas no MSVC e não aparece no MinGW nem em outras plataformas.
  • Quando a thread principal adquire um lock exclusivo e depois várias threads filhas tentam adquirir locks compartilhados, ocorre um "deadlock" em cerca de 1 a cada 1000 vezes.
  • Quando o deadlock acontece, exatamente 1 thread filha consegue adquirir o lock compartilhado com sucesso, e as demais threads filhas ficam bloqueadas para sempre em lock_shared().
  • Esse problema foi observado com std::shared_mutex, std::shared_lock/std::unique_lock e também ao chamar diretamente as funções de SRW.

Exemplo de código e reprodução do bug

  • Foi fornecido um código simples capaz de reproduzir o problema.
  • O código repete o processo em que a thread principal adquire um lock exclusivo, várias threads filhas adquirem locks compartilhados e depois os liberam.
  • Esse código mostra um bug relacionado a std::shared_mutex apenas na implementação do Windows com MSVC.

Opinião dos especialistas

  • Um desenvolvedor da STL comentou que isso parece ser um bug da API do Windows.
  • Houve discussão sobre os passos adequados para relatar o bug, e o desenvolvedor da STL fez o reporte internamente.
  • Outros usuários investigaram o problema em detalhes e contribuíram para isolar um bug específico na implementação de SRWLock.

Opinião do GN⁺

  • Este artigo traz informações especialmente importantes para desenvolvedores C++. O possível bug em std::shared_mutex pode afetar os mecanismos de sincronização de aplicações multithread.
  • Se o bug for confirmado, isso pode afetar a confiança na implementação da biblioteca padrão de C++. Os desenvolvedores precisam estar cientes desse tipo de problema e talvez considerar mecanismos alternativos de sincronização.
  • Esse problema pode ser especialmente importante em sistemas de alto desempenho ou de tempo real, nos quais um deadlock pode ter consequências críticas.
  • Antes de adotar essa tecnologia, os desenvolvedores devem realizar testes extensivos na plataforma e no compilador em uso para verificar se esse tipo de bug não está presente.
  • Para lidar com esse tipo de problema, os desenvolvedores podem considerar bibliotecas alternativas de sincronização, como a Boost. Como a Boost é amplamente testada e usada em muitas plataformas, ela pode oferecer uma alternativa confiável para esse tipo de situação.

1 comentários

 
GN⁺ 2024-03-04
Comentários do Hacker News
  • Um usuário se pergunta por que um problema tão básico não foi descoberto por tanto tempo e menciona uma resposta convincente fornecida por outro usuário. Ele aponta que uma thread que tenta adquirir o bloqueio em modo compartilhado pode, por engano, obter o bloqueio em modo exclusivo. Isso ocorre por causa da sobreposição de operações atômicas de teste e definição de bits quando a thread que adquire em modo compartilhado e a thread que libera em modo exclusivo são executadas ao mesmo tempo.

    • Um usuário explica que há um código de reprodução em que, durante a aquisição de um bloqueio compartilhado, todas as outras threads aguardam para adquirir o bloqueio compartilhado, e por isso, se alguma thread de trabalho obtiver por engano o bloqueio exclusivo, pode ocorrer um deadlock. Em casos de uso normais, as threads não esperam umas pelas outras, então o deadlock não acontece.
  • Outro usuário diz que não se surpreende com bugs sutis em bloqueios Reader/Writer e compartilha sua experiência de ter trabalhado em uma implementação interna baseada em Win32 antes do C++11 e do std::shared_mutex. Ele afirma que, por causa de experiências ruins com bloqueios compartilhados, tenta evitá-los a menos que sejam absolutamente necessários.

    • Um usuário compartilha uma experiência negativa com bloqueios compartilhados, dizendo que o desempenho de std::shared_mutex é visivelmente pior que o de std::mutex e que fazer double buffering dos dados é mais rápido.
  • Um usuário aponta que o título é enganoso e explica que o bug real está no bloqueio slim reader/writer (SRW) da Windows API, tendo sido descoberto porque std::shared_mutex foi implementado usando o bloqueio SRW. Um funcionário da Microsoft confirma que o bug foi reportado internamente à equipe da Windows API.

    • Um usuário comenta sobre o título enganoso e menciona que o problema real está no bloqueio SRW da Windows API, e que um funcionário da Microsoft confirmou que o bug foi reportado.
  • Um usuário se pergunta se o mesmo problema ocorre na implementação do WINE e diz que também gostaria de testar em sua própria instalação personalizada do XP. Nessa instalação, ele adicionou várias extensões, incluindo a API SRW, e afirma ter aplicado um patch no kernel para corrigir uma condição de corrida que causava deadlock na API de keyed event baseada na implementação de SRW.

    • Um usuário se pergunta se o mesmo problema acontece na implementação do WINE e diz que quer testar em sua instalação personalizada do XP. Nessa instalação, ele adicionou várias extensões, incluindo a API SRW, e aplicou um patch no kernel para corrigir uma condição de corrida que causava deadlock na API de keyed event baseada na implementação de SRW.
  • Foi apontado que há um bug no programa. Ele mistura variáveis não atômicas e atômicas no loop de verificação com yield(), e variáveis não atômicas não garantem coerência de cache entre threads. Por causa disso, o loop pode executar para sempre.

    • Um usuário aponta o bug no programa e explica o problema causado pelo uso misto de variáveis atômicas e não atômicas. Ele menciona que variáveis não atômicas não garantem coerência de cache, o que pode fazer o loop rodar indefinidamente.
  • Um usuário comenta que esse bug remonta à versão Vista de 2008 e expressa surpresa pelo fato de ninguém tê-lo descoberto por tanto tempo. Ele menciona que, no uso comum de rwlock, podem ocorrer casos aleatórios em que o bloqueio compartilhado não é adquirido, mas sem deadlock.

    • Um usuário comenta que esse bug existe desde o Vista e se surpreende por ele não ter sido descoberto por tanto tempo. Ele menciona que, no uso normal de rwlock, não ocorre deadlock, mas podem existir casos em que o bloqueio compartilhado não é adquirido.
  • Um usuário diz que é muito difícil reportar bugs da Windows API e critica o fato de orientarem as pessoas a usar o Feedback Hub, o que quase não funciona. Ele relata ter reportado um bug em que o SRWLOCK pode entrar em deadlock quando várias threads de leitura tentam adquirir juntas a posse compartilhada depois que o dono exclusivo libera a posse.

    • Um usuário menciona que reportar bugs da Windows API é muito difícil e critica a baixa eficácia do Feedback Hub. Ele compartilha que reportou um bug relacionado ao SRWLOCK.
  • Um usuário relembra que, no passado, ao comprar produtos da MS, era possível receber incidentes de suporte, e que, quando um bug real era encontrado, o incidente de suporte era reembolsado. Ele comenta que isso era útil para desenvolvedores e também um bom sistema para a MS, pois fornecia feedback para encontrar problemas reais e melhorar a documentação. Ele se pergunta se esse programa ainda existe.

    • Um usuário relembra os incidentes de suporte incluídos com produtos da MS e comenta que esse sistema era útil tanto para desenvolvedores quanto para a MS. Ele se pergunta se esse programa ainda existe hoje.
  • Por fim, um usuário expressa frustração com a dificuldade de reportar bugs da Windows API.

    • Um usuário expressa frustração com a dificuldade de reportar bugs da Windows API.