Ліміт на реальний (не процесорний!) час роботи скрипту,PHPClub - клуб розробників PHP
Dmitry Koteroff
Ліміт на реальний (не процесорний!) час роботи скрипта
set_time_limit() в Unix встановлює ліміт на ЧИСТИЙ ПРОЦЕСОРНИЙ час роботи скрипта. Чи можна в якийсь спосіб обмежити РЕАЛЬНИЙ час роботи?
Поясню, навіщо це потрібне. Функція ibase_query() у режимі транзакції IBASE_WAIT (очікуваної) у разі конфлікту може "підвисати" на невизначений час (поки ресурс не звільниться). Потрібно зробити, щоб це підвисання тривало не більше 10 секунд, а потім видавалося повідомлення і скрипт завершувався.
Я поки що не знайшов працюючого способу. Пробував: - set_time_limit() - declare(ticks=1) - pcntl_alarm() (на жаль, цієї функції немає в mod_php, тільки в cgi!)
Можливо, хтось ще знає метод?
TeaM PHPClub
Administrator
Це стандартно вирішується за допомогою alarm/signal, мабуть є якісь причини чому це не реалізовано для mod_php, як варіант пропасти апача на предмет такої функціональності, щоб він сам прибивав таких "довгих" чилдів, звичайно це не найкращий варіант.
P.S. почитав про обробку сигналів в mod_perl там теж проблеми у них, судячи з усього, єдино нормальний спосіб це обробляти це в апаче
Dmitry Koteroff
> мабуть, є якісь причини чому це не > реалізовано для mod_php Є і вони прості: Apache сам використовує SIGALRM. Я нещодавно в цьому якраз колупався (щоправда, для інших речей), тож на сумному досвіді знаю, як там усе заплутано.
Демона, звісно, можна. Тільки з тим розрахунком, що прибивати потрібно не будь-який скрипт, якщо він висить 10 с, а тільки той, що висить усередині ibase_query(). Бо можуть бути скрипти, які працюють довгоцілком легально (наприклад, скрипт прийому multipart-форми може цілу годину працювати, і її не можна чіпати). Так що демон повинен якось визначати, в якому стані скрипт, і робити відповідні дії.
В принципі, можна, мабуть, і без демона: нехай скрипт пише кудись і постійно оновлює свій PID і поточний статус, а на початку роботи - сканує це все і прибиває зажерлих (posix_kill). Тобто. кожен наступний запит прибиває частину існуючих.
Криво це все, звісно.
Administrator
prodigy-обдарована дитина
а якщо без ipc, а просто fork()? + в environment виставляємо дочці час скільки натискати ну а під доча сама знайде.
ще можна спробувати дістати дескриптор з'єднання з ресурсу з'єднання і зробити просто select з таймаутом
TeaM PHPClub
si>варіант з демоном якось красивіше виглядає IMO не дуже красиво і дуже заморочено. з гармати по горобцях.
AnToXa>ще можна спробувати дістати дескриптор з'єднання з ресурсу з'єднання та >зробити просто select з таймаутом
prodigy-обдарована дитина
Administrator
Dmitry Koteroff
> з гармати по горобцях Ось і я теж схиляюся до такої думки.
> просто fork() Низя в mod_php!
> netstat -an --program grep $IB_PORT grep httpd grep ESTABLISHED На жаль, так не вийде - бо має бути заборонено прибивати довгограючі процеси, які тримають з'єднання з IB, але при цьому НЕ ВИСЯТЬ в очікуванні в ibase_query(), а роблять щось ще (наприклад, скрипт розсилки).
Взагалі краще уникати таких "довгих" транзакцій до IB/Firebird.
А чи можна поцікавитися, чому саме WAIT транзакція? Зазвичай вони і призводять до Deadlock-у, щовласне, і спостерігається.
Якщо це Web-додаток, то чому не використовувати NO WAIT?
Або як альтернативу, можна спробувати зменшити інтервал DEADLOCK_TIMEOUT який відповідає за час, який будуть "висіти" заблоковані транзакції.
Dmitry Koteroff
> може сенс допрацювати ibase-лібу на предмет > таймууту? Можливо. Але я не бачу, як це зробити, якщо використання SIGALRM недоступне.
Коротко сухий залишок такий. Дідлок - це коли A чекає B, а B чекає A, і це буде гарантовано відбуватися до нескінченності, якщо тільки A або B не відвалиться. Такі ситуації легко розпізнаються (наявність циклів у якихось там графах точно вже не пам'ятаю). А "довге очікування" - це зовсім навіть не дідлок, тому що це не взаємне очікування, а просто очікування транзакції A транзакцією B (але не навпаки). Відповідно, IB розпізнає дідлоки, але термін "розпізнати довге очікування" безглуздий - бо нічого кримінального в "довгому очікуванні" немає.
NOWAIT використовувати не можна! І ОСОБЛИВО - у web-області. Посудіть самі: запустять 2 людини одночасно той самий скрипт, і у випадку NOWAIT один з них відвалиться з помилкою. Це некоректна поведінка! У таких випадках другий скрипт повинен почекати, доки вирішаться всі конфлікти з першим, і коректно виконатися.
Є ще варіант: у циклі довбати запит у NOWAIT-режимі, а якщо не вийшло, то почекати секунду (або випадковий інтервал) і повторити ще раз – і так протягом 10 секунд. В принципі, такий спосіб робітник (схема використовується, наприклад, при колізіях пакетів в Ethernet-мережах), проте він КРИВИЙ - тому що призводить до зайвих простоїв у разі великої кількості одночасних запитів.