2012-06-01 2 views
2

J'ai eu le plaisir exprès de déboguer pendant des heures un peu bizarre dans la conception d'Apache 2.4 en construisant un module multiplateforme. Le problème auquel j'ai dû faire face est qu'Apache, au démarrage, charge deux fois le fichier de configuration et charge le module lui-même deux fois. Une fois que je devine pour tester la configuration et lire la commande struct et ensuite la suivante pour remplir les espaces pour le serveur à exécuter. Cela ne poserait normalement aucun problème, mais j'avais besoin de charger la configuration de mon module au moment du chargement avant de servir les clients et d'analyser les besoins de mon module UNE FOIS SEULEMENT. Étant donné que j'utilise un certain nombre de ressources, y compris des bases de données et autres, j'ai décidé que l'exécution multiple n'est pas la meilleure idée, en particulier lors de la prise de hits sur un serveur de base de données.Développer des modules Apache inter-plateformes en utilisant ap_retained_data_create/get in Post Read Config

Le manuel en ligne ("Developer API 2.5") indique au lieu d'utiliser une ancienne méthode, que je laisserai au lecteur de rechercher, d'utiliser ap_retained_data_get et ap_retained_data_create pour conserver les données lors du déchargement des modules. De préférence, passer un drapeau à la phase suivante que vous avez déjà passé la phase de test.

Ici se trouve le mal de tête. Ce n'est pas comme ça que ça fonctionne sur Windows.

Répondre

2

Linux fonctionne en deux passes, mais Windows fonctionne en quatre étapes.

utilisant cette méthode dans le crochet lire config post fonctionne pour Linux, mais pas 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 

    } 

S'il vous plaît noter que je suis exportation code C++ dans mes modules, d'où l'utilisation des classes. De plus, certaines déclarations de variables sont absentes pour des raisons de concision.

Donc, cela devrait être suffisant pour Windows non? Faux. J'ai dû apprendre cela en arrière parce que je construis d'abord sur Windows, mais Windows a quatre passes au lieu de deux. Là pour votre initialisation fonctionnera encore deux fois.

Ma prochaine solution est la suivante:

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

Semblait travailler .... Ok, je suis fait avec cette partie, non? FAUX! Je suis passé à la boîte Linux et la ville segfault. Je suis sûr que beaucoup de développeurs Apache aguerris secouent probablement la tête en ce moment, mais ce sont les mêmes gars qui ne documentent pas ces problèmes.

Mon dernier correctif était d'envelopper le code Windows dans des blocs définis. Je ne suis pas sûr s'il y avait un meilleur moyen ou pas, mais cela a fonctionné pour moi. Ainsi, les travaux suivants sur les deux plates-formes sans 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 
    }   

Espérons que quelqu'un d'autre puisse en bénéficier.

+0

La fonction fileExists est un wrapper autour des différentes routines apr_io pour déterminer si un fichier existe. –