سؤال

أقوم ببناء بعض تطبيقات FastCgi ، وهو نوع من الأخطاء التي لا تقتلها Lighttpd بعد أن أصبحت خاملة ، لذلك أحاول إغلاقهم بمفردهم.

حاولت استخدام

signal(SIGALRM, close);
alarm(300);

وجعل الوظيفة الوثيقة تنفيذ مخرج (0) ، وهذا يعمل بشكل جيد تقريبًا.

المشكلة هي أن الوظيفة الإغلاق يتم استدعاؤها في كل مرة يتم فيها تشغيل حلقة البرنامج الرئيسية على الرغم من (أسمي المنبه (300) كل حلقة لإعادة تعيينها). لقد قرأت صفحة MAN لـ ARARARD () ولا يبدو الأمر كما لو أن تسميتها عدة مرات بنفس القيمة يجب أن تتجول SIGALRM ، لذلك أفترض أن LIGHTTPD ترسل إشارة إنذار.

السؤال الكبير! هل هناك طريقة لتشغيل طريقة بعد فاصل محدد ، وأن تكون هذه الفاصل الزمني قابلاً للاستحماء بدون Sigalrm؟ سأكون لطيفًا إذا كان بإمكاني الحصول على أجهزة إنذار متعددة أيضًا.

هذا التطبيق كله حتى الآن:

#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
#include "fcgiapp.h"

FCGX_Stream     *in, *out, *err;
FCGX_ParamArray envp;
int calls = 0;

void print(char*, ...);
void close();

int main(void)
{
        // If I'm not used for five minutes, leave
        signal(SIGALRM, close);

        int reqCount = 0;

        while (FCGX_Accept(&in, &out, &err, &envp) >= 0)
        {
                print("Content-type: text/plain\r\n\r\n");

                int i = 0;
                char **elements = envp;
                print("Environment:\n");
                while (elements[i])
                        print("\t%s\n", elements[i++]);

                print("\n\nDone. Have served %d requests", ++reqCount);
                print("\nFor some reason, close was called %d times", calls);

                alarm(300);
        }

        return 0;
}

void print(char *strFormat, ...)
{
        va_list args;
        va_start(args, strFormat);
        FCGX_VFPrintF(out, strFormat, args);
        va_end(args);
}

void close()
{
        calls++;
//      exit(0);
}
هل كانت مفيدة؟

المحلول

أفضل طريقة هي: إضافة مؤشر ترابط بحيث يمكنك إزالة الإشارة والإنذار ، ومزامنة الخيط والرمز الرئيسي الخاص بك (مؤشر الترابط الرئيسي).

نصائح أخرى

ربما كنت أستخدم أجهزة توقيت Posix. لا يتعين على أجهزة ضبط الوقت استخدام الإشارات. لديك خيار بين عدم الإخطار على الإطلاق ، رفع إشارة ، أو تشغيل وظيفة كخيط جديد (الذي سأفعله لأنه لن يتداخل مع FastCGI).

تأكد من تضمينك <signal.h> و <time.h>, وربط مع -lrt

أولاً ، سأملأ هيكل سيجيفينت الخاص بك:

struct sigevent myTimerSignal = {
    .sigev_notify = SIGEV_THREAD,
    .sigev_notify_function = close //Make sure you change your function declaration to close(union sigval), you do not need to use the sigval unless you store data in your event too
};

الآن قم بإنشاء جهاز التوقيت الخاص بك:

timer_t myTimer;
if(timer_create(CLOCK_REALTIME, &myTimerSignal, &myTimer)){
    //An error occurred, handle it
}

يتيح تسليحه ، سوف يستدعي Close () في موضوع جديد في 300 ثانية:

struct itimerspec timeUntilClose = {
    .it_value = {
        .tv_sec = 300 //300 seconds
    }
};

if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
    //Handle the error
}

الآن ، يجب أن يكون لديك مؤقت جاهزًا لإيقاف البرنامج بعد 300 ثانية. أعلم أنني قد أتأخر ، لكنني آمل أن يساعد هذا القارئ في المستقبل.

ربما يمكنك لف وظيفة الإغلاق بوظيفة أخرى ستدعو أولاً النوم ()؟

الحجة إلى alarm المكالمة ثوان, وليس دقائق. لذلك أنت تطلب الاستيقاظ في 5 ثوانٍ بعد كل مرة من خلال الحلقة الرئيسية.

إليك الحل الذي يتجنب نوع السؤال ، لكنه يعمل. سوف يستجيب فقط لأحداث إشارة التطبيق الخاصة بي:

void close(int intSignal, siginfo_t *info, void *context)
{
        // For some stupid reason MY signal doesn't populate siginfo_t
        if (!info)
        {
                count++;
        }
}

إذا كان بنية siginfo فارغة ، فذلك لأن المنبه () تعثره. إذا كانت هناك عملية خارجية ، يتم ملء siginfo_t.si_pid بصفر.

ما زلت لا أحب هذا الحل ، لكنه يعمل. المشكلة الغريبة الآن هي أن القيام بمخرج (0) لا يغلق التطبيق ، على الرغم من أن Lighttpd يعتقد أنه قد انتهى ويولد آخر. هذا يعني أنني الآن لدي عمليات Rouge. raise(SIGUSR1) وهو ما من المفترض أن يوقف البرامج النصية fastcgi لا يبدو أنه يقوم بالخدعة أيضًا ... هممم ...

يبقى السؤال: كيف يمكن للاتصال بوظائف غير متزامنة في مؤقت فاصل دون استخدام إشارات؟

  • حاول إغلاق جميع واصفات الملفات (بما في ذلك stdin و stdout). هذا يجب أن يغلق مثيل CGI إذا كان الخمول.
  • يمكنك استخدام select() مع مهلة لجدولة بدلا من sigalrm
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top