[Moscow.pm] Ограничить время выполнения произвольной функции

Dmitry Karasik dmitry на karasik.eu.org
Пт Янв 29 05:23:45 PST 2010


я с alarm не очень дружу, он в перле странноват. Например мне вот это
нравится из perlipc:

If a signal of any given type fires multiple times during an opcode (such as
from a fine-grained timer), the handler for that signal will only be called
once after the opcode completes, and all the other instances will be discarded.
Furthermore, if your system's signal queue gets flooded to the point that there
are signals that have been raised but not yet caught (and thus not deferred) at
the time an opcode completes, those signals may well be caught and deferred
during subsequent opcodes, with sometimes surprising results.  For example, you
may see alarms delivered even after calling alarm(0) as the latter stops the
raising of alarms but does not cancel the delivery of alarms raised but not yet
caught.

однако я видел на цпане overload::eval, он правда нерабочий, но если автор его
подточит, я думаю будет самое оно.


/dk

On Fri, Jan 29, 2010 at 01:06:25PM +0300, Dmitry E. Oboukhov wrote:
> стоит сабжевая задача.
> 
> Для ее решения я пошел по пути описанному в perldoc -f alarm (на CPAN
> есть штук пяток модулей на эту тему например Sys::AlarmCall (он же
> рекомендован к употреблению в perlfaq), я про них знаю, но описанная
> здесь проблема в них во всех проявляется, потому стоит задача
> написания нового модуля, либо прийти к нереализуемости задачи), итак,
> в perldoc -f alarm пример:
> 
>    eval {
>        local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
>        alarm $timeout;
>        $nread = sysread SOCKET, $buffer, $size;
>        alarm 0;
>    };
>    if ($@) {
>        die unless $@ eq "alarm\n";   # propagate unexpected errors
>        # timed out
>    }
>    else {
>        # didn't
>    }
> 
> 
> пишем вместо sysread ту функцию, которую хотим ограничить по времени
> работы и вуаля - работает. Если посмотреть CPAN'овские модули, то все
> они работают на этой технологии, только дополнительно делают следующие
> вещи:
>     - определяют контекст вызова wantarray
>     - запоминают/восстанавливают предыдущее значение alarm 
>     - ловят исключения в самой функции
>     - прочий сервисный шняг
> но это несущественно, собственно вернемся к проблеме.
> 
> допустим мы заменили sysread на foo()
> 
> и как оказывается работа сей конструкции зависит от того чтоже там
> внутри foo()
> 
> допустим foo у нас содержит такой код:
> 
> sub foo
> {
>     for ($i = 0; $i < 100; $i++) {
>     	sleep 1;
>     }
> }
> 
> с такой функцией будет все ок.
> 
> но вот если например внутри функции хотя бы в одном месте будет eval
> sub foo
> {
>     for ($i = 0; $i < 100; $i++) {
>     	eval "sleep 1";
>     }
> }
> 
> то именно этот eval и получит die "alarm\n".
> Теперь все зависит от функции, распространит она die выше или не
> распространит. можно было бы сказать что функция которая не
> распространяет die - "неправильная", да только таких функций в
> cpan-модулях чуть меньше чем дохрена, да и "правильные есть"
> 
> sub divide($$)
> {
>     my ($a, $b) = @_;
>     die "на ноль делить нельзя" unless $b;
>     return $a / $b;
> }
> 
> тот кто использует divide знает что исключение может быть выброшено
> строго в одном случае и может его просто поймать и не распространить
> дальше, а скажем изменить алгоритм основной работы итп.
> 
> Получается хоть функция приведенная в perldoc -f alarm SIGALRM и
> словила, но тормознуть выполнение "подопытной" функции не может, если
> тот содержит eval.
> 
> Искал искал решение, но пока ничего приемлемого не нашел. 
> Может кто боролся с подобной проблемой? есть какие-либо предложения?
> 
> в обработчике SIGALRM мы в принципе видим стек вызовов, можно ли
> как-то из него изъять несколько уровней? perl'овыми средствами
> 
> -- 
> ... mpd is off
> 
> . ''`.                               Dmitry E. Oboukhov
> : :???  :   email: unera на debian.org jabber://UNera@uvw.ru
> `. `~???              GPGKey: 1024D / F8E26537 2006-11-21
>   `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537



> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org


-- 
Sincerely,
	Dmitry Karasik



Подробная информация о списке рассылки Moscow-pm