2012-06-01 1 views
2

Я с удовольствием отлаживал часовые причуды в дизайне Apache 2.4 при создании кроссплатформенного модуля.Разработка кроссплатформенных модулей Apache с использованием ap_retained_data_create/get in Post Read Config

Проблема, с которой я столкнулся, заключается в том, что Apache при запуске дважды загружает конфигурационный файл и, следовательно, загружает сам модуль дважды. Как только я догадаюсь проверить конфигурацию и прочитать структуру команд, а затем следующую, чтобы заполнить пробелы для запуска сервера. Обычно это не было проблемой, но мне нужно было загружать конфигурацию моего модуля во время загрузки, прежде чем обслуживать клиентов, и только анализировать потребности моего модуля ТОЛЬКО И ТОЛЬКО ОДИН РАЗ.

Поскольку я использую несколько ресурсов, включая базы данных и т. П., Я решил запустить несколько раз, это не самая лучшая идея, особенно когда вы делаете хиты на сервере базы данных.

В онлайн-руководстве («API разработчика 2.5») говорится вместо старого метода, который я оставил читателю для поиска, чтобы использовать ap_retained_data_get и ap_retained_data_create, чтобы сохранить данные при разгрузке модуля. Желательно передать флаг на следующий этап, который уже прошел этап тестирования.

Здесь находится головная боль. В Windows это не так.

ответ

2

Linux работает в два прохода, но Windows работает в четыре прохода.

Используя этот метод в посте конфигурации чтения крюка работает для 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 имеет четыре прохода вместо двух. Там для вашей инициализации все равно будет работать дважды.

Мой следующий раствор следующим образом:

// 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 в определенные блоки. Я не уверен, был ли лучший способ или нет, но это сработало для меня. Таким образом, на обеих платформах работает без segfault.

// 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 
    }   

Надеюсь, кто-то может воспользоваться этим.

+0

Функция fileExists - это оболочка вокруг различных процедур apr_io, чтобы определить, существует ли файл. –