Абсолютно чудовищный в своей тупости баг между программным обеспечением Docker и Razer под Windows обнаружил пользователь твиттера Foone.
Суть проблемы заключалась в том, что на компьютере Foone одновременно отказывались запускаться Docker и ПО Razer Synapse — утилита по управлению хоткеями, RGB-подсветкой и прочими маркетинговыми свистелками «геймерских» девайсов.
Foone решил не сдаваться и начал копать, почему абсолютно не связанные между собой типы программного обеспечения — существующие, фактически, в разных мирах продукты — конфликтуют между собой и не дают запускаться друг другу.
Важно отметить, что проблема существует и работает в обе стороны: если запущено ПО от Razer — не запускается Docker, если запущен Docker — не работает ПО Razer.
После небольшого расследования Foone обнаружил, что и Docker, и Razer Synapse используют механизм контроля запуска двух копий приложения в виде глобального мьютекса через проверку GUID сборки ПО в .NET. А вот тут начинается самый ад.
Для прохождения проверки используется код вида:
И вроде как, все выглядит неплохо, но в этом коде есть ошибка. Часть
И суть нашего прекрасного бага в том, что Docker и Ryzer Synapse обращаются к одной и той же части .NET в своей работе. То есть на уровне глобального мьютекса они обе — одно и тоже ПО. Причем эта ошибка допущена как в коде Docker, так и в коде Ryzer.
А теперь вопрос: откуда взялась эта ошибка с
Год спустя ошибку заметили и Cerebrus вернулся и откомментился, но удалить своей предыдущий ответ не смог.
В мае 2018 года разработчики Docker отчитались об исправлении ошибки с GUID, но некорректно настроенный мьютекс с привязкой к библиотеке, а не версии, может вызывать конфликты между многими другими программными продуктами. Например, похожая история случалась еще в 2003 году, а ошибка в коде Docker просуществовала неизвестно сколько лет, пока не была исправлена.
Суть проблемы заключалась в том, что на компьютере Foone одновременно отказывались запускаться Docker и ПО Razer Synapse — утилита по управлению хоткеями, RGB-подсветкой и прочими маркетинговыми свистелками «геймерских» девайсов.
Foone решил не сдаваться и начал копать, почему абсолютно не связанные между собой типы программного обеспечения — существующие, фактически, в разных мирах продукты — конфликтуют между собой и не дают запускаться друг другу.
Важно отметить, что проблема существует и работает в обе стороны: если запущено ПО от Razer — не запускается Docker, если запущен Docker — не работает ПО Razer.
После небольшого расследования Foone обнаружил, что и Docker, и Razer Synapse используют механизм контроля запуска двух копий приложения в виде глобального мьютекса через проверку GUID сборки ПО в .NET. А вот тут начинается самый ад.
Для прохождения проверки используется код вида:
string.Format("Global\{0}", (object) Assembly.GetExecutingAssembly().GetType().GUID);
И вроде как, все выглядит неплохо, но в этом коде есть ошибка. Часть
GetType()
тут вообще лишняя, потому что она обращается к типу сборки System.Reflection.RuntimeAssembly
, а не к версии. А по System.Reflection.RuntimeAssembly
возвращается информация о самом .NET. В итоге наш глобальный мьютекс проверяет не копию ПО, а обращение ПО к части самого .NET. И суть нашего прекрасного бага в том, что Docker и Ryzer Synapse обращаются к одной и той же части .NET в своей работе. То есть на уровне глобального мьютекса они обе — одно и тоже ПО. Причем эта ошибка допущена как в коде Docker, так и в коде Ryzer.
А теперь вопрос: откуда взялась эта ошибка с
GetType()
? Интернет услужливо сообщает, что подобный вопрос с использованием глобального мьютекса был задан на всем нам известном Stackoverflow еще в 2009 году пользователем «Nathan». Буквально спустя 12 минут ему ответил пользователь «Cerebrus», который и предложил использовать вышеуказанную конструкцию, которая, в сути своей, ошибочна. Год спустя ошибку заметили и Cerebrus вернулся и откомментился, но удалить своей предыдущий ответ не смог.
В мае 2018 года разработчики Docker отчитались об исправлении ошибки с GUID, но некорректно настроенный мьютекс с привязкой к библиотеке, а не версии, может вызывать конфликты между многими другими программными продуктами. Например, похожая история случалась еще в 2003 году, а ошибка в коде Docker просуществовала неизвестно сколько лет, пока не была исправлена.