Re[34]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 11.07.14 10:20
Оценка:
Здравствуйте, Erop, Вы писали:

BFE>>А разве не является первейшей задачей программиста проверить вводимые значения на валидность?

E>Это не всегда просто и не всегда быстро.
E>Скажем обрабатываем мы какой-то очень большой файл в несколько потоков, на какой-то момент концы не сошлись с концами. Что делаем?

Вариантов много, но вот надёжный путь к краху — игнорировать.
Если заранее нельзя проверить целостность данных, то необходимо такую проверку делать в момент обработки, что чревато проблемами, если в ходе обработки программа меняет другие данные.
Ну и потом, обработка ошибочных ситуаций — это существенный процент кода. Сколько — не считал, но в строках, думаю, процентов 30 будет.
И каждый день — без права на ошибку...
Re[35]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 11.07.14 11:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>И почему, кстати, взаимодействие потоков вы называете низкоуровневым кодом?

EP>>Не взаимодействие потоков, а использование низкоуровневых примитивов типа mutex, condition_variable, atomic, etc.
BFE>ok. Допустим. Расшифруйте подробнее, что значит "локализуем низкоуровневый многопоточный код в модуле"? Запуск всех ниток программы должен происходить в одном модуле?

Через примитивы этого модуля. Самый простой пример — параллельные вычисления, можно использовать готовые высокоуровневые примитивы, вместо ручного создания потоков и их синхронизации при каждой необходимости.

EP>>Проверил на значение близкое к нулю и выбросил исключение, об этом и речь выше. (иногда дешевле делать проверки в ходе вычислений, а не сразу при получении данных, но это другой вопрос)

BFE>ok. А почему взаимодействия потоков не попадают под эту концепцию?

Я же говорю, что могут — если мы действительно видим, что на определённых данных может задедлочиться, и намеренно кидаем исключение. А не так, что "тут не должно быть deadlock'ов, но всё-таки кинем исключение".

EP>>>>В то же время, например, можно элементарно придумать ситуацию, в которой плохие входные данные приведут к выходу за границы массива.

BFE>>>С таким подходом я согласиться никак не могу.
EP>>С каким подходом?
BFE>Когда входные данные позволяют обратится по адресам за пределами массива.
EP>>Вполне жизненный пример выхода за границы массива из-за плохих данных: в начале файла идут значения некоторых узлов, а в конце ссылки на них в виде индексов, неправильный индекс может выйти за границы массива.
BFE>Если нет проверки в момент обращения по индексу, то вас ожидают проблемы поддержки.

Так я же говорю, что для таких случаев vector::at вполне оправдан, так как в этом случае выход за пределы — вполне ожидаемый вариант.

EP>>Теперь можно пример хитрого алгоритма, который дедлочится на плохих данных?

BFE>Нет в этом ничего хитрого. Из практики. Программа занимается корректированием пары изображений. Пользователь задаёт списки файлов на обработку. Если пользователь в одной обработке задаёт пару file1.tif file2.tif, а в другой file2.tif file1.tif, то иногда два потока блокируют друг друга: каждый из потоков открывает первый список из файла, а второй открыть не может, так как он открыт другим потоком. Дальше всё зависит от обработки такой ситуации, если первый файл остаётся открытым...

Обработку открытия уже открытого файла нужно предусматривать даже если у нас только один файл.
Пример более-менее валидный, но всё же — тут скорее не "хитрость", а недоработка. Интересует deadlock, который оставили преднамеренно, ради каких-то выгод.
Re[34]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 11.07.14 11:23
Оценка:
Здравствуйте, Erop, Вы писали:

E>Мало того, когда мы кидаем и ловим исключение, мы можем дать таки какие-то гарантии на целостность данных.


Так да, но где гарантия что что мы его поймаем? Код уже скомпрометирован, в нём баг приведший в неизвестное состояние.
Ты летишь на самолёте, автопилот сильно и очень резко отклонился от заданного курса, решаешь сесть на ближайший аэродром — будешь сам рулить, или попросишь автопилот?

E>А если грубо убиваем процесс, то вообще никаких гарантий дать не можем. Даже того, что внутри-программные кэши все сбросились на диск


Если этот deadlock детектится изнутри, то в нашем assert'е можно точно также сбросить все критичные кэши.
Re[35]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 11.07.14 11:25
Оценка:
Здравствуйте, Erop, Вы писали:

EP>>Речь-то как раз о том, что исключение вылетевшее из неизвестного состояния далеко не факт что вообще сможет дойти до обработчика на верхнем уровне.

EP>>Шанс успешного прибития процесса (находящегося в неизвестном состоянии) намного выше шанса того, что исключение (вылетевшее неизвестно откуда и как) доберётся до обработчика и ничего не сломает по пути.
E>Это очень зависит от стратегии использования исключений и обработки ошибок в программе...

Покажи пример, где процесс убить не получилось, а исключение может успешно долететь до обработчика.
Re[35]: Deadlock-prevention алгоритм
От: Erop Россия  
Дата: 13.07.14 19:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

E>>А если грубо убиваем процесс, то вообще никаких гарантий дать не можем. Даже того, что внутри-программные кэши все сбросились на диск


EP>Если этот deadlock детектится изнутри, то в нашем assert'е можно точно также сбросить все критичные кэши.


В своём потоке -- да...

Вообще не понятно, чем тут дедлок специфичен.
Приход в дедлок -- это провал assert'а. А уж как в вашей программе принято обрабатывать провал assert'а, -- вопрос отдельный.
Есть вполне удачные программы, в которых провал assert'а приводит к броску исключения...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[36]: Deadlock-prevention алгоритм
От: Erop Россия  
Дата: 13.07.14 19:34
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Покажи пример, где процесс убить не получилось, а исключение может успешно долететь до обработчика.

Ну, например, если ты даёшь гарантии готовности к исключениям, и ловишь исключения только на самом верхнем уровне, то всё получится...

При этом я согласен, что если вообще забить на раии и готовность к исключениям, а критичные ресурсы и кэши регать в статическом регистраторе, и в случае чего сбрасывать и освобождать централизовано, то будет более надёжная конструкция.

Но это не значит, что подход с раии и исключениями неправильный...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[36]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 13.07.14 23:45
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>А если грубо убиваем процесс, то вообще никаких гарантий дать не можем. Даже того, что внутри-программные кэши все сбросились на диск

EP>>Если этот deadlock детектится изнутри, то в нашем assert'е можно точно также сбросить все критичные кэши.
E>В своём потоке -- да...

Так этот вариант и обсуждается — исключение ведь тоже сам поток и выбрасывает.

E>Вообще не понятно, чем тут дедлок специфичен.

E>Приход в дедлок -- это провал assert'а. А уж как в вашей программе принято обрабатывать провал assert'а, -- вопрос отдельный.

Это уже перевод дискуссии в терминологическое поле, в то время как речь изначально шла про аварийное завершение (как его не назови) vs выброс исключения.

E>Есть вполне удачные программы, в которых провал assert'а приводит к броску исключения...


Да, например
Re[37]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 14.07.14 00:12
Оценка:
Здравствуйте, Erop, Вы писали:

EP>>Покажи пример, где процесс убить не получилось, а исключение может успешно долететь до обработчика.

E>Ну, например, если ты даёшь гарантии готовности к исключениям, и ловишь исключения только на самом верхнем уровне, то всё получится...

Во-первых, чем же это надёжней убийства процесса?
Во-вторых, это не даёт никаких гарантий что исключение долетит до обработчика. Например, во время раскрутки стэка нетривиальный деструктор (а в более-менее большом приложении трудно дать гарантии того, что все деструкторы тривиальны) может залезть в live-lock, или другой поток (участвовавший в этом самом межпоточном взаимодействии, приведшем к deadlock'у) может начать расстреливать всё подряд — код скомпрометирован, мы в неизвестном состоянии, может произойти всё что технически возможно.

E>При этом я согласен, что если вообще забить на раии и готовность к исключениям, а критичные ресурсы и кэши регать в статическом регистраторе, и в случае чего сбрасывать и освобождать централизовано, то будет более надёжная конструкция.

E>Но это не значит, что подход с раии и исключениями неправильный...

Опять таки, я не говорил про то, что нужно забить на RAII и исключения.
Мой поинт в том, что если в программе откровенный баг (коим незапланированный deadlock и является), приведший в неизвестное состояние — то "всё пропало", и при его обнаружении runtime нужно склеить ласты ASAP. В тех же редких случаях, когда нужна некоторая отказоустойчивость, проброс исключения через скомпрометированный код — далеко не самый надёжный вариант.
При этом отказ от использования исключений для выхода из неизвестного состояния — не означает отказ от исключений вообще.
Re[17]: Deadlock-prevention алгоритм
От: SkyDance Земля  
Дата: 14.07.14 00:48
Оценка:
BFE>Была какая-то странная сборка. Может там и был epoll, но вот даже стандартных средств доступа к последовательным портам не было.
BFE>Да, как обычно: open, cfsetospeed, poll, write...

В двух рядом стоящих предложениях — противоречие. Раз вы открываете fd, и делаете poll — значит, нет никаких противопоказаний к epoll. Более чем уверен, банальным незнанием вы сами создали себе проблемы. Впрочем, это для джуниоров нормально. Шишки надо же где-то набивать.

BFE>Ну, например. Для работы с сетью мы используем стороннюю библиотеку с callback'ами и функцией ожидания. Как предлагаете подключить её к epoll?


Что за "сторонняя библиотека", и зачем вы ее используете? Опять же, "функция ожидания" сторонней библиотеки — это что-то из epoll/poll/select (другие науке малоизвестны).

BFE>Эээ... Может я чего-то не понимаю? Когда вы говорите об epoll, то сколько ниток исполнения вы предполагаете?


Столько, сколько необходимо для обеспечения требуемой latency. Если, к примеру, ваш код ответа на какие-то входные данные работает 5 мс, и на такое долгое время нельзя выключать какие-то еще обработчики, потребуется запустить более одного потока.

BFE>Да. У нас 15 независимых библиотек.


Да хоть 25. Количество библиотек не является показателем монолитности проекта. Более того, реализация паттерна "реактор" (тот самый epoll) явно будет сидеть где-то в библиотеке base/common/utils или как у вас там называется общая библиотека примитивов. Наличие паттерна "рекатор" не означает монолитность проекта.
Re[18]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 15.07.14 10:08
Оценка:
Здравствуйте, SkyDance, Вы писали:

BFE>>Была какая-то странная сборка. Может там и был epoll, но вот даже стандартных средств доступа к последовательным портам не было.

BFE>>Да, как обычно: open, cfsetospeed, poll, write...
SD>В двух рядом стоящих предложениях — противоречие. Раз вы открываете fd, и делаете poll — значит, нет никаких противопоказаний к epoll. Более чем уверен, банальным незнанием вы сами создали себе проблемы. Впрочем, это для джуниоров нормально. Шишки надо же где-то набивать.
Здесь нет противоречия. Разница между тем, что было, и тем, что сейчас — несколько лет.

BFE>>Ну, например. Для работы с сетью мы используем стороннюю библиотеку с callback'ами и функцией ожидания. Как предлагаете подключить её к epoll?

SD>Что за "сторонняя библиотека", и зачем вы ее используете?
Да какая разница? Библиотеки мы используем ровно для того, для чего их пишут.

SD>Опять же, "функция ожидания" сторонней библиотеки — это что-то из epoll/poll/select (другие науке малоизвестны).

Разумеется. И что это меняет? Вы предлагаете переписывать сторонюю библиотеку под свои нужды?

BFE>>Эээ... Может я чего-то не понимаю? Когда вы говорите об epoll, то сколько ниток исполнения вы предполагаете?

SD>Столько, сколько необходимо для обеспечения требуемой latency. Если, к примеру, ваш код ответа на какие-то входные данные работает 5 мс, и на такое долгое время нельзя выключать какие-то еще обработчики, потребуется запустить более одного потока.
Ок. А теперь вернёмся к теме топика: как обеспечить передачу данных между этими нитками?

BFE>>Да. У нас 15 независимых библиотек.

SD>Да хоть 25. Количество библиотек не является показателем монолитности проекта.
А что является?
И каждый день — без права на ошибку...
Re[19]: Deadlock-prevention алгоритм
От: SkyDance Земля  
Дата: 15.07.14 23:18
Оценка:
BFE>Здесь нет противоречия. Разница между тем, что было, и тем, что сейчас — несколько лет.

Окей, несколько — это сколько? 12 лет? Впрочем, даже 12 лет назад уже вовсю был select — и, раз уж вы применяли poll, reactor pattern был более чем применим.

BFE>Да какая разница? Библиотеки мы используем ровно для того, для чего их пишут.


Да такая разница. Название в студию, благо, сетевых библиотек не так и много, и все из них достаточно гибкие, чтобы их можно было встроить в нужный софт без костылей типа десятка потоков.

BFE>Разумеется. И что это меняет? Вы предлагаете переписывать сторонюю библиотеку под свои нужды?


Вот чтобы понять, что предложить, мне и нужно знать конкретику — что за библиотека-то?

BFE>Ок. А теперь вернёмся к теме топика: как обеспечить передачу данных между этими нитками?


Поскольку все нитки сидят в цикле реактора, передача данных будет организована путём пересылки сообщений. Благо, необходимость в синхронизации отсутствует.

SD>>Да хоть 25. Количество библиотек не является показателем монолитности проекта.

BFE>А что является?

А это надо у вас спросить. Вы же сетуете, мол, "применение паттерна reactor сделает проект монолитным". В традиционном понимании "монолитный" проект — это такой, из которого нельзя вынуть модуль и заменить на его апгрейднутую версию. Иными словами, монолит — это нечто с сильными связями и завязкой на внутреннюю логику работы.
Re[20]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 16.07.14 10:31
Оценка:
Здравствуйте, SkyDance, Вы писали:

SD>Окей, несколько — это сколько? 12 лет? Впрочем, даже 12 лет назад уже вовсю был select — и, раз уж вы применяли poll, reactor pattern был более чем применим.

Изначально poll не применялся.

BFE>>Да какая разница? Библиотеки мы используем ровно для того, для чего их пишут.

SD>Да такая разница. Название в студию, благо, сетевых библиотек не так и много, и все из них достаточно гибкие, чтобы их можно было встроить в нужный софт без костылей типа десятка потоков.
Я не уверен в том, что имею право разглашать названия используемых библиотек.

BFE>>Ок. А теперь вернёмся к теме топика: как обеспечить передачу данных между этими нитками?

SD>Поскольку все нитки сидят в цикле реактора, передача данных будет организована путём пересылки сообщений. Благо, необходимость в синхронизации отсутствует.
ok. И сколько таких очередей будет?

SD>А это надо у вас спросить. Вы же сетуете, мол, "применение паттерна reactor сделает проект монолитным". В традиционном понимании "монолитный" проект — это такой, из которого нельзя вынуть модуль и заменить на его апгрейднутую версию. Иными словами, монолит — это нечто с сильными связями и завязкой на внутреннюю логику работы.


В любом проекте можно переписать его существенный кусок. Модульным проект можно назвать только если его компоненты используются в нескольких проектах.
И каждый день — без права на ошибку...
Re[21]: Deadlock-prevention алгоритм
От: SkyDance Земля  
Дата: 17.07.14 00:00
Оценка:
BFE>Изначально poll не применялся.

Все равно что-то применялось для ожидания. В самом деле, не active wait же.

BFE>Я не уверен в том, что имею право разглашать названия используемых библиотек.


Даже не знаю, плакать или смеяться. Нельзя разглашать название библиотеки, использованной в неизвестном продукте неизвестных поставщиков. Не иначе как редкая хакерская либа libssl...

BFE>ok. И сколько таких очередей будет?


В точности равное количеству уровней приоритета в вашей системе. Чтобы запросы от более приоритетных устройств могли вытеснять обработку менее приоритетных задач.
Если, конечно, у вас вообще есть приоритеты. У запускаемых вашим нынешним софтом потоков приоритеты у всех одинаковые, или различаются? Если различаются, то почему?

BFE>В любом проекте можно переписать его существенный кусок. Модульным проект можно назвать только если его компоненты используются в нескольких проектах.


И? Продолжай мысль, объясняй, почему применение reactor pattern сделает проект "монолитным". И заодно ответь — ведь есть же у вас некая базовая библиотека (utils, base, common, ...).
Re[22]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 17.07.14 09:36
Оценка:
Здравствуйте, SkyDance, Вы писали:

BFE>>Изначально poll не применялся.

SD>Все равно что-то применялось для ожидания. В самом деле, не active wait же.
sleep(..) ну и блокирующие операции io, конечно же.

BFE>>Я не уверен в том, что имею право разглашать названия используемых библиотек.

SD>Даже не знаю, плакать или смеяться. Нельзя разглашать название библиотеки, использованной в неизвестном продукте неизвестных поставщиков. Не иначе как редкая хакерская либа libssl...
Узнать, кто я и где я работаю, как два байта переслать. Но не в этом дело.

BFE>>ok. И сколько таких очередей будет?

SD>В точности равное количеству уровней приоритета в вашей системе. Чтобы запросы от более приоритетных устройств могли вытеснять обработку менее приоритетных задач.
И все они будут проходить через основную нитку?
SD>Если, конечно, у вас вообще есть приоритеты. У запускаемых вашим нынешним софтом потоков приоритеты у всех одинаковые, или различаются? Если различаются, то почему?
Есть, но это не очень важно.

BFE>>В любом проекте можно переписать его существенный кусок. Модульным проект можно назвать только если его компоненты используются в нескольких проектах.

SD>И? Продолжай мысль, объясняй, почему применение reactor pattern сделает проект "монолитным".
Может я чего-то не знаю, но разве для использования библиотеки с reactor pattern, библиотека не должна представлять специальный интерфейс для такой работы? Ну, например, легко ли Boost.Asio использовать с этим патерном?

SD> И заодно ответь — ведь есть же у вас некая базовая библиотека (utils, base, common, ...).

нет такой. В utils'ах у нас только логи и всякая мелочь, типа boost.enum.
И каждый день — без права на ошибку...
Re[23]: Deadlock-prevention алгоритм
От: SkyDance Земля  
Дата: 18.07.14 00:05
Оценка:
BFE>Узнать, кто я и где я работаю, как два байта переслать. Но не в этом дело.

Никто даже и пытаться не будет. Тем более что выяснить, какие библиотеки используются в продукте, особого труда не составит.
А дело, по-видимому, лишь в том, что библиотека уже использует что-то reactor-based

BFE>И все они будут проходить через основную нитку?


Вы вообще понимаете, как работает epoll и аналоги? Ниток (и дескрипторов epoll) будет столько, сколько у вас разных приоритетов. Среди них нет "главной" или "основной". Просто, в соответствии с приоритетом потока, обработка более приоритетных вещей сможет прерывать что-то менее приоритетное. Если вам такие прерывания не нужны, тогда не нужны и потоки — все можно обрабатывать в одном.

BFE>Есть, но это не очень важно.


Это очень важно. При отсутствии приоритетных задач вам многозадачность (и многопоточность) вообще не нужны.

BFE>Может я чего-то не знаю, но разве для использования библиотеки с reactor pattern, библиотека не должна представлять специальный интерфейс для такой работы? Ну, например, легко ли Boost.Asio использовать с этим патерном?


Как бы так помягче... boost::asio реализует этот паттерн их io_service есть прямая реализация.
Re[24]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 18.07.14 08:39
Оценка:
Здравствуйте, SkyDance, Вы писали:

BFE>>И все они будут проходить через основную нитку?

SD>Вы вообще понимаете, как работает epoll и аналоги?
Примерно.

SD>Ниток (и дескрипторов epoll) будет столько, сколько у вас разных приоритетов. Среди них нет "главной" или "основной". Просто, в соответствии с приоритетом потока, обработка более приоритетных вещей сможет прерывать что-то менее приоритетное. Если вам такие прерывания не нужны, тогда не нужны и потоки — все можно обрабатывать в одном.

All reactor systems are single threaded by definition, but can exist in a multithreaded environment.


Значит, если есть несколько ниток с разными приоритетами, значит это уже не reactor pattern.
Но вопрос не в этом. Допустим у вас несколько приоритетов => несколько ниток. Ранее вы писали, что хотите организовать передачу данных с помощью сообщений. Положим, для примера, что ниток 3 штуки и всем им нужна информация друг друга. Опишите способ обмена этой информацией.

BFE>>Есть, но это не очень важно.

SD>Это очень важно. При отсутствии приоритетных задач вам многозадачность (и многопоточность) вообще не нужны.
Ну хорошо. Приоритет работы с сетью не равен приоритету работы с устройствами.

BFE>>Может я чего-то не знаю, но разве для использования библиотеки с reactor pattern, библиотека не должна представлять специальный интерфейс для такой работы? Ну, например, легко ли Boost.Asio использовать с этим патерном?

SD>Как бы так помягче... boost::asio реализует этот паттерн их io_service есть прямая реализация.
Я знаю, что boost::asio реализует этот паттерн. Но вопрос-то не в этом!
Давайте, покажите как использовать boost::asio совместно со своим reactor pattern.
И каждый день — без права на ошибку...
Re[25]: Deadlock-prevention алгоритм
От: SkyDance Земля  
Дата: 21.07.14 04:27
Оценка:
BFE>All reactor systems are single threaded by definition, but can exist in a multithreaded environment.

Вот я про то и писал, что если вам нужно больше одного реактора — запускайте больше одного.

BFE>Значит, если есть несколько ниток с разными приоритетами, значит это уже не reactor pattern.


Не угадал: это значит, что у вас два отдельных процесса (или потока, это не суть важно), и в каждом из них крутится свой реактор. Сие нужно для того (и только для того) чтобы обеспечить приоритетную обработку.

BFE>Но вопрос не в этом. Допустим у вас несколько приоритетов => несколько ниток. Ранее вы писали, что хотите организовать передачу данных с помощью сообщений. Положим, для примера, что ниток 3 штуки и всем им нужна информация друг друга. Опишите способ обмена этой информацией.


Надо рассматривать конкретную систему и конкретную информацию. Что за данные разделяются между ветками. Обязательно ли обеспечивать их согласованность, или можно, к примеру, делать так, чтобы более приоритетные задачи выполнялись безусловно, а затем посылали update message в менее приоритетные. Короче, нужно продумывать архитектуру. С учётом имеющихся ограничений. А то, может статься, нет никаких проблем и вовсе одним реактором обойтись.

BFE>Давайте, покажите как использовать boost::asio совместно со своим reactor pattern.


Может, наоборот? Использовать буст-овский реактор со своими задачами. Это намного логичнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.