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
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.
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 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_mutexestaba 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 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.
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 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 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
SRWLOCKpuede 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 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.
Por último, un usuario expresó su decepción por lo difícil que es reportar bugs de la API de Windows.