Существуют разные способы реализовать одновременную обработку данных: fork, threads, event loop… и, насколько я понимаю, вместе они уживаются довольно паршиво.
Давайте возьмём event loop и fork. Есть ли смысл использовать их в одном приложении? На первый взгляд — конечно, есть! Event loop будет нормально работать только при условии, что обработчики событий отрабатывают достаточно быстро. И как только какой-то обработчик начинает требовать много времени для работы, первое что приходит в голову — отforkнуть его в отдельный процесс (в принципе есть ещё и нити, но в perl с ними туго, так что этот вариант даже не рассматриваем).
Но это на первый взгляд. А если копнуть глубже…
Например, приложение на базе event loop может иметь кучу предустановленных таймеров, которые сработают через некоторое время и вызовут определённые события. И тут делается fork… и что, порождённый процесс должен унаследовать все эти таймеры и события? Или всё-таки нет? Или должен унаследовать их частично, выборочно? Бред…
Ещё один момент: обычно когда fork вызывается в обычном, линейном приложении, мы четко представляем себе состояние приложения в момент вызова fork, и как это состояние нужно изменить в порождённом процессе сразу после вызова fork (закрыть лишние FD, разобраться с сигналами, etc.). В случае же event loop мы, находясь в обработчике конкретного события, общее состояние приложения представляем себе очень приблизительно, мягко говоря!
Вообще, у нормального приложения на базе event loop весь код находится в функциях — обработчиках событий. Т.е. когда вызывается fork, мы по определению находимся в такой функции. И куда мы из неё выйдем, в порождённом процессе? А куда нас выкинет по исключению (die)?
Более жизненный пример. Приложение использует epoll для мультиплексирования множества открытых сокетов. И тут, обработчик какого-то события делает fork. Во-первых порождённый процесс унаследует FD самого epoll. Во-вторых он унаследует кучу сокетов (FD) открытых в родителе. В результате родитель начинает получать от epoll самые неожиданные и странные события, по разным причинам.
Вообще-то этот вопрос достаточно абстрактный, и конкретно с Perl или Linux/epoll не связан.
Я протестировал CPAN-модули Event и Event::Lib — оба не содержат никакой особой обработки fork, и даже не упоминают все эти, связанные с fork, проблемы в документации.
Perl6 будет поддерживать event loop прямо в ядре… и я пока не вижу, как он может обойти эти проблемы.
В общем, или я упускаю из виду что-то важное на уровне концепций, или здесь таки прикопана конкретная, взлослая грабля. Буду рад любым пояснениям по этому вопросу.
Давайте возьмём event loop и fork. Есть ли смысл использовать их в одном приложении? На первый взгляд — конечно, есть! Event loop будет нормально работать только при условии, что обработчики событий отрабатывают достаточно быстро. И как только какой-то обработчик начинает требовать много времени для работы, первое что приходит в голову — отforkнуть его в отдельный процесс (в принципе есть ещё и нити, но в perl с ними туго, так что этот вариант даже не рассматриваем).
Но это на первый взгляд. А если копнуть глубже…
Например, приложение на базе event loop может иметь кучу предустановленных таймеров, которые сработают через некоторое время и вызовут определённые события. И тут делается fork… и что, порождённый процесс должен унаследовать все эти таймеры и события? Или всё-таки нет? Или должен унаследовать их частично, выборочно? Бред…
Ещё один момент: обычно когда fork вызывается в обычном, линейном приложении, мы четко представляем себе состояние приложения в момент вызова fork, и как это состояние нужно изменить в порождённом процессе сразу после вызова fork (закрыть лишние FD, разобраться с сигналами, etc.). В случае же event loop мы, находясь в обработчике конкретного события, общее состояние приложения представляем себе очень приблизительно, мягко говоря!
Вообще, у нормального приложения на базе event loop весь код находится в функциях — обработчиках событий. Т.е. когда вызывается fork, мы по определению находимся в такой функции. И куда мы из неё выйдем, в порождённом процессе? А куда нас выкинет по исключению (die)?
Более жизненный пример. Приложение использует epoll для мультиплексирования множества открытых сокетов. И тут, обработчик какого-то события делает fork. Во-первых порождённый процесс унаследует FD самого epoll. Во-вторых он унаследует кучу сокетов (FD) открытых в родителе. В результате родитель начинает получать от epoll самые неожиданные и странные события, по разным причинам.
Вообще-то этот вопрос достаточно абстрактный, и конкретно с Perl или Linux/epoll не связан.
Я протестировал CPAN-модули Event и Event::Lib — оба не содержат никакой особой обработки fork, и даже не упоминают все эти, связанные с fork, проблемы в документации.
Perl6 будет поддерживать event loop прямо в ядре… и я пока не вижу, как он может обойти эти проблемы.
В общем, или я упускаю из виду что-то важное на уровне концепций, или здесь таки прикопана конкретная, взлослая грабля. Буду рад любым пояснениям по этому вопросу.