если выполняется очень тяжелая логика, то я делал fork/wait + alarm
2010/1/29 Dmitry E. Oboukhov <[email protected]>: > стоит сабжевая задача. > > Для ее решения я пошел по пути описанному в 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: [email protected] jabber://[email protected] > `. `~’ GPGKey: 1024D / F8E26537 2006-11-21 > `- 1B23 D4F8 8EC0 D902 0555 E438 AB8C 00CF F8E2 6537 > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.10 (GNU/Linux) > > iEYEAREDAAYFAktisyEACgkQq4wAz/jiZTdEEACgumiLhm31+IWlasr2HDEvOdy1 > pjkAoKODwg5xIwcwIALTe6JLrbzY3zYo > =vnbh > -----END PGP SIGNATURE----- > > -- > Moscow.pm mailing list > [email protected] | http://moscow.pm.org > > -- Moscow.pm mailing list [email protected] | http://moscow.pm.org
