Ліміт на реальний (не процесорний!) час роботи скрипту,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-мережах), проте він КРИВИЙ - тому що призводить до зайвих простоїв у разі великої кількості одночасних запитів.