Страниц: [1]
  Печать  
Автор Тема: Блинчик  (Прочитано 2190 раз)
oder
Гость
« : Ноября 24, 2009, 11:50:41 pm »

Уже второй раз нарываюсь на взаимоблокировку в менеджере ресурса.
Один поток обрабатывает open(). При этом он захватил мютекс  доступа до объекта (чтоб провалидировать путь и защитить объект от изменений состояния/удаления, пока будет происходить открытие файла) - вещь, ИМХО, вполне нормальная и распространённая. При вызове iofunc_open_default(), библиотека пробует заблокировать аттрибут файла через iofunc_attr_lock().
Другой поток обрабатывает сообщение на другом OCB того же объекта того же аттрибута (например, write или devctl) и для него библиотека сама, втихаря, ещё перед вызовом обработчика, блокирует аттрибут. Понятно, поток попадает в обработчик, пробует захватить мютекс объекта (которого держит поток, ожидающий в iofunc_open_default()) и происходит взаимная блокировка.
Ну а как же вообще тогда работать в нескольких потоках?
В предыдущем случае я заткнул дыру тем, что взял в ещё один мютекс dispatch_handler(), чтоб потоки более чем по одному в библиотеку не лезли. При этом, там есть такие приколы, что если тебе хочется отпустить этот мютекс ещё до выхода из обработчиков (чтоб не держать dispatch во время ответа по сети и не создавать таким образом инверсию приоритетов) - ты ж, вроде, уже все свои дела сделал - можно и отпустить - так вот, этого делать просто так, не проанализоровав код библиотеки нельзя! Ибо опять нарвёшься на грабли! Прикол в том, что обработчик close() может вызываться ещё и сам по себе, с инициативы библиотеки (для запросов, которые приходят по имени и создают себе внутри временный OCB, или ещё для чего). И, если мютекс отпустить, его в обработчике close() надо опять назад захватывать, чтоб не полезли грабли.
Короче, куча навороченной синхронизации, которая нигде не описана и до которой нормальный программист впринципе не может самостоятельно додуматься, не ковыряясь в нутрях библиотеки менеджера ресурсов. И это только для того, чтоб устранить заложенную в ней потенциальную взаимную блокировку, устранить инверсию приоритетов на захвате аттрибутов (ибо товарищи поленились и сделали его через слипоны вместо мютексов) и потерять при этом всю многопоточность.
Как же они сами этим пользуются? Неужели у них многопоточность тестировалась лишь на уровне примеров из справочной системы?
Записан
oder
Гость
« Ответ #1 : Ноября 25, 2009, 10:29:59 pm »

Ценой убитого дня и больших напрягов я его, всё-таки, поборол.
На сей раз, путём отпускания мютекса объекта (благо, код позволяет) с повтором захвата и всех валидаций ещё раз после iofunc_open_default(). Если, пока мютекс был отпущен, объект убьют, OCB помечается как невалидный (а их там 4 вида бывает) и футболит прочь все операции. На время прохода через iofunc_open_default() память аттрибута держится живой с помощью мютекса верхнего уровня (защищающего список объектов от удалений), а потом (в случае неудачи повторных валидаций) - с помощью счётчика ссылок.
Короче, жуткие навороты. Sad Smiley
« Последнее редактирование: Ноября 25, 2009, 10:34:52 pm от oder » Записан
Страниц: [1]
  Печать  
 
Перейти в: