2

クロス プラットフォーム モジュールを構築する際に、Apache 2.4 の設計の特異な部分を何時間もデバッグできたことは、私にとって大きな喜びでした。

私が直面した問題は、起動時にApacheが構成ファイルを2回ロードし、モジュール自体を2回ロードすることです。構成をテストしてコマンド構造体を読み取り、次にサーバーを実行するための空白を埋めると思います。これは通常は問題になりませんが、ロード時にモジュールの構成をロードしてからクライアントにサービスを提供し、モジュールのニーズを一度だけ解析する必要がありました。

私はデータベースなどを含む多くのリソースを使用しているため、特にデータベース サーバーでヒットを取得する場合は、複数回実行することは最善の方法ではないと判断しました。

オンライン マニュアル ("Developer API 2.5") では、モジュールのアンロード後もデータを保持するために ap_retained_data_get と ap_retained_data_create を使用する古い方法を使用する代わりに、読者に調べてもらうように指示しています。できれば、テスト段階をすでに通過したというフラグを次の段階に渡します。

ここが頭の痛いところです。これは、Windows での動作方法ではありません。

4

1 に答える 1

2

Linux は 2 パスで動作しますが、Windows は 4 パスで動作します。

構成後の読み取りフックでこのメソッドを使用すると、Linux では機能しますが、Windows では機能しません。

    // variables for base config start
    const char  *flag = "some_prefixed_flag_to_mashup_with_other_flags";
    void        *init_flag = NULL;
    int         dbl = APLOG_TRACE4;
    // logger
    logging logger(NULL, s, p);     
    // determine if this is the first time we have loaded
    init_flag = ap_retained_data_get(flag);
    // check flag result
    if (init_flag == NULL) 
    {
        // breakpoint
        stdLog(logger, INFX_LOG_DATA, dbl);
        // set first time flag local
        ap_retained_data_create(flag, 1);
    }
    // call initization routine
    else
    {
        // do something here

    }

モジュールで C++ コードをエクスポートしているため、クラスを使用していることに注意してください。また、簡潔にするために一部の変数宣言は省略されています。

これでWindowsには十分なはずですよね?違う。最初に Windows でビルドしているので、これを逆方向に学習する必要がありましたが、Windows には 2 つではなく 4 つのパスがあります。あなたの初期化はまだ2回実行されます。

私の次の解決策は次のとおりです。

    // variables for base config start
    const char  *flag = "some_prefixed_flag_to_mashup_with_other_flags";
    void        *init_flag = NULL;
    char        *pidname;
    int         dbl = APLOG_TRACE4;
    pid_t       pidNKey;
    apr_file_t  *pidfile;       
    // logger
    logging logger(NULL, s, p);     
    // determine if this is the first time we have loaded
    init_flag = ap_retained_data_get(flag);
    // check flag result
    if (init_flag == NULL) 
    {
        // breakpoint
        stdLog(logger, INFX_LOG_DATA, dbl);
        // set first time flag local
        ap_retained_data_create(flag, 1);
    }
    else
    {
        // break point
        stdLog(logger, INFX_LOG_DATA, dbl);
        // create a pid if not exists
        if (ap_read_pid(p, "logs/httpd.pid", &pidNKey) == OK)
        {
            // break point
            stdLog(logger, INFX_LOG_DATA, dbl);
            // create a pid especially for our setup
            pidname = apr_psprintf(ptemp, "logs/infx.%d.pid", pidNKey);
            // if pidfile does not exist then create it
            if (!fileExists(pidname, ptemp))
            {
                // break point
                stdLog(logger, INFX_LOG_DATA, dbl);
                // create the pid
                apr_file_open(&pidfile, pidname, APR_WRITE|APR_APPEND|APR_CREATE, INFX_BASE_PERM, ptemp);
                // add nonsensical data to it
                apr_file_puts("1", pidfile);
                // cllose the file and wait for run 2
                apr_file_close(pidfile);
            }
            // begin work
            else 
            {
                // break point
                stdLog(logger, INFX_LOG_DATA, dbl);
                // we no longer require the pid file
                apr_file_remove(pidname, ptemp);
            }
        }
    }

うまくいったようです....わかりました、その部分は終わりましたよね?違う!Linux ボックスと segfault シティに行き着きました。ベテランの Apache 開発者の多くはおそらく今、首を横に振っていると思いますが、これらの問題を文書化していないのは同じ人たちです。

私の最後の修正は、定義ブロックで Windows コードをラップすることでした。より良い方法があるかどうかはわかりませんが、うまくいきました。したがって、以下はセグメンテーション違反なしで両方のプラットフォームで機能します。

    // variables for base config start
    const char  *flag = "some_prefixed_flag_to_mashup_with_other_flags";
    void        *init_flag = NULL;
    int         dbl = APLOG_TRACE4;
    // logger
    logging logger(NULL, s, p);     
    // determine if this is the first time we have loaded
    init_flag = ap_retained_data_get(flag);
    // check flag result
    if (init_flag == NULL) 
    {
        // breakpoint
        stdLog(logger, INFX_LOG_DATA, dbl);
        // set first time flag local
        ap_retained_data_create(flag, 1);
    }
    // call initization routine
    else
    {
        // break point
        stdLog(logger, INFX_LOG_DATA, dbl);
        #if defined(WIN32)
        // create a pid if not exists
        if (ap_read_pid(p, "logs/httpd.pid", &pidNKey) == OK)
        {
            // break point
            stdLog(logger, INFX_LOG_DATA, dbl);
            // create a pid especially for our setup
            pidname = apr_psprintf(ptemp, "logs/infx.%d.pid", pidNKey);
            // if pidfile does not exist then create it
            if (!fileExists(pidname, ptemp))
            {
                // break point
                stdLog(logger, INFX_LOG_DATA, dbl);
                // create the pid
                apr_file_open(&pidfile, pidname, APR_WRITE|APR_APPEND|APR_CREATE, INFX_BASE_PERM, ptemp);
                // add nonsensical data to it
                apr_file_puts("1", pidfile);
                // cllose the file and wait for run 2
                apr_file_close(pidfile);
            }
            // begin work
            else 
            {
                // break point
                stdLog(logger, INFX_LOG_DATA, dbl);
                // we no longer require the pid file
                apr_file_remove(pidname, ptemp);
        #endif
                // do something here for both platforms
        #if defined(WIN32)
            }
        }
        // crash if we do get a proper pid
        else
        {
            // breakpoint
            stdLog(logger, INFX_LOG_DATA, APLOG_CRIT, "HTTPD File not found? A Bug?");
            // set status
            return HTTP_INTERNAL_SERVER_ERROR;
        }
        #endif
    }           

うまくいけば、他の誰かがこれから恩恵を受けるかもしれません。

于 2012-06-01T06:08:50.477 に答える