PDA

View Full Version : توقف یا عدم توقف اجرای برنامه هنگامی که کاربر روی دکمه Stop مرورگر کلیک میکند!



eshpilen
پنج شنبه 28 اردیبهشت 1391, 19:04 عصر
این نکتهء جالبیه که شاید خیلی ها ندونن.
الان یک تستی در این ارتباط انجام دادم گفتم بذارم تا شما هم ببینید.

فرض کنید کاربر صفحهء سایت شما رو باز میکنه و برنامهء PHP شما داره یک پردازش سنگین/طولانی انجام میده که ممکنه چند ثانیه طول بکشه.
حالا کاربر میاد وقتی هنوز پردازش درخواست در سمت سرور تمام نشده، روی دکمهء Stop مرورگر کلیک میکنه یا اصلا مرورگر رو میبنده (یا از صفحهء جاری به صفحهء دیگری میره).
نتیجهء این عمل این میشه که بنا به تنظیم پیکربندی PHP در این زمینه، برنامهء شما ممکنه در نیمهء اجرای خودش متوقف بشه. و درواقع تنظیم پیشفرض PHP روی حالتی هست که اینچنین بشه!

اسم این تنظیم ignore_user_abort است که میتونید در فایل php.ini پیداش کنید. اگر مقدارش روی 0 یا off باشه به این معنی است که وقتی کاربر روی دکمهء Stop کلیک میکنه یا به هر دلیل دیگری کانکشن TCP بسته میشه، اجرای برنامهء شما هم متوقف میشه.

البته یه نکتهء قابل توجه اینکه PHP وقتی بعد از قطع شدن ارتباط اجرای برنامه رو متوقف میکنه که چیزی رو به خروجی و به سمت کلاینت ارسال میکنه. احتمالا دلیل این قضیه اینه که از نظر فنی تا زمانیکه PHP یک خروجی رو به کلاینت ارسال نکرده متوجه قطع شدن ارتباط نمیشه.

خب اینکه برنامهء شما بدون اینکه اجراش کامل شده باشه خاتمه پیدا بکنه میتونه خیلی وقتا نامطلوب باشه و حتی در سمت سرور موجب ایجاد مشکل بشه. مثلا فرض کنید که از کوئری های دیتابیس برنامهء شما چندتاش اجرا بشه اما چندتای دیگش اجرا نشه! واضحه که این ممکنه باعث ناسازگار شدن داده های دیتابیس بشه. البته من شخصا این قضیه رو با دیتابیس تست نکردم، اما بهرحال بهتون میگم تا اگر چنین موردی داشتید سرنخ رو داشته باشید. میتونید خودتون این قضیه رو تست کنید، یا میتونید پیشاپیش احتیاط بکار برده و تنظیمات مربوطه رو در برنامه های خودتون در حالت امن قرار بدید به این شکل:


ignore_user_abort(true);

دستور بالا رو در ابتدای برنامه های خودتون قرار بدید، تا با Abort شدن اتصال کلاینت، برنامهء شما متوقف نشه. این دستور به PHP میگه که وضعیت اتصال با کلاینت رو نادیده بگیره و همچنان به کار خودش ادامه بده.

خب من یک تستی هم برای این قضیه درست کردم که میتونید انجام بدید.
البته من تست رو روی لوکال ویندوز انجام دادم و باید بدونید که این برنامه نیاز داره پرمیشن ایجاد فایل در دایرکتوری محل قرارگیری خودش رو داشته باشه (قابل توجه کسانی که روی لینوکس تست میکنن).

این کد رو در فایل test.php ذخیره کنید:


<?php

ignore_user_abort(false);

$i=1;
while(true) {
echo 'x';
@ ob_flush(); flush();
touch($i);
sleep(2);
$i++;
}

?>

حالا test.php رو در مرورگر خودتون باز کنید (http://localhost/test.php).
بعد به فولدری این که test.php درش هست نگاه کنید. هر یک ثانیه یک بار کلید F5 رو بزنید تا نمایش محتویات فولدر رفرش بشه و فایلهای ایجاد شده رو مشاهده کنید. دقت کنید دکمهء F5 رو در مرورگر نزنید، منظور من زدن دکمهء F5 موقع مشاهدهء فولدر ویندوزه که باعث میشه نمایش فایلهای فولدر رفرش بشه و اگر فایل جدیدی ایجاد شده ظاهر بشه.
برنامهء ما که در داخل یک حلقهء بینهایت قرار داره هر 2 ثانیه یک فایل ایجاد میکنه. فایلها از فایل با اسم 1 شروع میشه و همینطور فایل با اسم 2 و 3 و الی آخر.
خب حالا دکمهء Stop مرورگر رو بزنید.
خواهید دید که بعد از یکی دو ثانیه اجرای برنامهء ما هم متوقف شده و دیگه فایلی ایجاد نمیشه.
این به این معناست که با زدن دکمهء Stop مرورگر، اجرای برنامه در سمت سرور هم متوقف شده.

حالا خط اول کد رو به این تغییر داده و سیو کنید:


ignore_user_abort(true);

فایلهای ایجاد شده توسط برنامه در تست قبلی رو Delete کنید تا تست جدیدی رو انجام بدیم.
حالا دوباره صفحه رو در مرورگر باز/رفرش کنید و ایجاد شدن فایلها رو تحت نظر بگیرید.
این بار میبینید که با کلیک کردن روی دکمهء Stop مرورگر، برنامه همچنان به کار خودش ادامه میده و فایلهای جدید همچنان هر 2 ثانیه یک بار ایجاد میشن (تا زمانیکه آپاچی رو متوقف کنید یا timeout سی ثانیه ای PHP فرا برسه).

eshpilen
پنج شنبه 28 اردیبهشت 1391, 19:23 عصر
البته اینم بگم که لزومی نداره همهء برنامه های خودتون رو طوری تنظیم کنید که با قطع ارتباط با کلاینت اجرای اونها خاتمه پیدا نکنه.
بهرحال این ویژگی هم حتما هدف و کاربردهای خودش رو داشته و داره. و اینکه میتونیم از طریق مرورگر برنامه رو متوقف کنیم بعضی وقتا میتونه مفید یا لازم باشه.
ولی من شخصا مورد خاصی الان بنظرم نمیرسه. بعدش هم بهرحال بصورت پیشفرض PHP اجرای برنامه ها رو بعد از 30 ثانیه خاتمه میده و امکان اینکه برنامه ای بخاطر باگی چیزی بصورت دائمی روی سرور درحال اجرا باقی بمونه و منابع سیستم رو هدر بده خیلی کمه مگر اینکه timeout اجرا رو روی نامحدود تنظیم کرده باشیم.

کسانی که تجربه و نظر و اطلاعات خاص بیشتری در این زمینه دارن میتونن مطالب تاپیک رو کامل کنن.

MMSHFE
پنج شنبه 28 اردیبهشت 1391, 19:42 عصر
یک مورد رو هم بد نیست تست کنید: اینکه محتوا رو توی OB بریزیم و بعد از تکمیل، یکجا ارسال کنیم. ببینید توی این حالت هم User_Abort کار میکنه؟