2 puntos por GN⁺ 2024-03-04 | 1 comentarios | Compartir por WhatsApp

Posible bug de std::shared_mutex en Windows

  • Un equipo de software descubrió un comportamiento inesperado relacionado con std::shared_mutex en Windows.
  • Este problema solo ocurre en MSVC, y no aparece en MinGW ni en otras plataformas.
  • Cuando el hilo principal adquiere un bloqueo exclusivo y luego varios hilos hijos intentan adquirir bloqueos compartidos, se produce un "deadlock" aproximadamente 1 de cada 1000 veces.
  • Cuando ocurre el deadlock, exactamente 1 hilo hijo logra adquirir el bloqueo compartido con éxito, y el resto de los hilos hijos queda bloqueado para siempre en lock_shared().
  • Este problema se observó al usar std::shared_mutex, std::shared_lock/std::unique_lock o al invocar directamente las funciones SRW.

Ejemplo de código y reproducción del bug

  • Se proporciona un código simple con el que se puede reproducir el problema.
  • El código repite el proceso en el que el hilo principal adquiere un bloqueo exclusivo, varios hilos hijos adquieren bloqueos compartidos y luego los liberan.
  • Este código muestra un bug relacionado con std::shared_mutex únicamente en la implementación de Windows MSVC.

Opinión de expertos

  • Un desarrollador de STL comentó que este problema parece ser un bug de la API de Windows.
  • Hubo una discusión sobre los pasos adecuados para reportar el bug, y el desarrollador de STL lo reportó internamente.
  • Otros usuarios investigaron el problema en detalle y contribuyeron a acotar un bug específico en la implementación de SRWLock.

Opinión de GN⁺

  • Este artículo ofrece información especialmente importante para desarrolladores de C++, porque un bug potencial en std::shared_mutex puede afectar los mecanismos de sincronización en aplicaciones multihilo.
  • Si se confirma el bug, esto podría afectar la confianza en la implementación de la biblioteca estándar de C++. Los desarrolladores deben estar al tanto de este tipo de problemas y quizá considerar mecanismos de sincronización alternativos.
  • Este problema puede ser especialmente importante en sistemas de alto rendimiento o en tiempo real, donde un deadlock puede tener consecuencias críticas.
  • Antes de adoptar esta tecnología, los desarrolladores deben realizar pruebas exhaustivas en la plataforma y el compilador correspondientes para verificar que no existan este tipo de bugs.
  • Para resolver problemas como este, los desarrolladores pueden considerar bibliotecas de sincronización alternativas como Boost. Como Boost ha sido ampliamente probado y se usa en muchas plataformas, puede ofrecer una alternativa confiable frente a este tipo de problemas.

1 comentarios

 
GN⁺ 2024-03-04
Opiniones de Hacker News
  • Un usuario se preguntó por qué un problema tan básico no se detectó durante tanto tiempo y mencionó una respuesta convincente que dio otro usuario. Señaló que un hilo que intenta adquirir el bloqueo en modo compartido puede, por error, obtenerlo en modo exclusivo. Esto ocurre por la superposición de operaciones atómicas de prueba y establecimiento de bits cuando un hilo adquiere en modo compartido y otro libera en modo exclusivo al mismo tiempo.

    • Un usuario explicó que tiene código de reproducción en el que todos los demás hilos esperan adquirir un bloqueo compartido mientras uno lo está adquiriendo, y que eso puede llevar a un interbloqueo si algún hilo de trabajo obtiene por error un bloqueo exclusivo. En los casos de uso habituales no ocurre interbloqueo porque los hilos no se esperan entre sí.
  • Otro usuario comentó que no le sorprenden los bugs sutiles en los bloqueos Reader/Writer y compartió su experiencia trabajando en implementaciones internas basadas en Win32 antes de C++11 y de std::shared_mutex. Dijo que, por sus malas experiencias con los bloqueos compartidos, intenta evitarlos salvo que sean absolutamente necesarios.

    • Un usuario compartió una experiencia negativa con los bloqueos compartidos y mencionó que el rendimiento de std::shared_mutex era notablemente peor que el de std::mutex, hasta el punto de que hacer doble buffering de los datos resultaba más rápido.
  • Un usuario señaló que el título es engañoso y explicó que el bug real está en el bloqueo slim reader/writer (SRW) de la API de Windows, y que se descubrió porque std::shared_mutex estaba implementado usando bloqueos SRW. Un empleado de Microsoft confirmó que el bug fue reportado internamente al equipo de la API de Windows.

    • Un usuario señaló que el título induce a error y mencionó que el problema real está en los bloqueos SRW de la API de Windows, además de que un empleado de Microsoft confirmó que el bug fue reportado.
  • Un usuario se preguntó si el mismo problema también ocurre en la implementación de WINE y comentó que le gustaría probarlo en su instalación personalizada de XP. Dijo que en esa instalación agregó varias extensiones, incluida la API de SRW, y que parchó el kernel para corregir una condición de carrera que causaba interbloqueos en la API de keyed event basada en la implementación de SRW.

    • Un usuario se preguntó si el mismo problema ocurre también en la implementación de WINE y comentó que quiere probarlo en su instalación personalizada de XP. En esa instalación agregó varias extensiones, incluida la API de SRW, y parchó el kernel para corregir una condición de carrera que causaba interbloqueos en la API de keyed event basada en la implementación de SRW.
  • Se señaló que hay un bug en el programa. Se están mezclando variables no atómicas y atómicas en el bucle de comprobación con yield(), y las variables no atómicas no garantizan coherencia de caché frente a otros hilos. Esto puede hacer que el bucle se ejecute para siempre.

    • Un usuario señaló un bug en el programa y explicó el problema que surge al mezclar variables no atómicas y atómicas. Mencionó que las variables no atómicas no garantizan coherencia de caché, por lo que el bucle puede ejecutarse indefinidamente.
  • Un usuario comentó que este bug se remonta hasta la versión Vista de 2008 y expresó su sorpresa de que nadie lo hubiera descubierto durante tanto tiempo. Mencionó que, en el uso normal de rwlock, pueden ocurrir casos aleatorios en los que no se logra adquirir un bloqueo compartido, pero sin que haya interbloqueo.

    • Un usuario comentó que este bug se remonta hasta Vista y expresó sorpresa de que no se hubiera detectado en tanto tiempo. También mencionó que, en el uso normal de rwlock, no hay interbloqueo, aunque sí pueden darse casos en los que no se consigue adquirir un bloqueo compartido.
  • Un usuario mencionó que reportar bugs de la API de Windows es muy difícil y criticó que le indiquen hacerlo a través de Feedback Hub, porque casi no sirve. Ese usuario reportó un bug en el que SRWLOCK puede caer en interbloqueo cuando varios hilos lectores intentan adquirir al mismo tiempo la propiedad compartida después de que el propietario exclusivo libera la propiedad.

    • Un usuario mencionó que reportar bugs de la API de Windows es muy difícil y criticó que hacerlo por medio de Feedback Hub no resulta efectivo. Compartió además que ya reportó un bug relacionado con SRWLOCK.
  • Un usuario recordó que antes, al comprar productos de MS, se recibían incidentes de soporte, y que si se encontraba un bug real, el incidente era reembolsado. Comentó que era un buen sistema porque beneficiaba a los desarrolladores y también a MS al proporcionar retroalimentación para detectar problemas reales y mejorar la documentación. Se preguntó si ese programa todavía existe.

    • Un usuario recordó los incidentes de soporte incluidos antes con productos de MS y comentó que ese sistema beneficiaba tanto a los desarrolladores como a MS. También se preguntó si ese programa todavía existe hoy.
  • Por último, un usuario expresó su decepción por lo difícil que es reportar bugs de la API de Windows.

    • Un usuario expresó su decepción por la dificultad de reportar bugs de la API de Windows.