Абсолютно чудовищный в своей тупости баг между программным обеспечением Docker и Razer под Windows обнаружил пользователь твиттера Foone.

Суть проблемы заключалась в том, что на компьютере 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 просуществовала неизвестно сколько лет, пока не была исправлена.