2012-06-01 2 views
2

크로스 플랫폼 모듈을 빌드하는 동안 아파치 2.4의 디자인에서 몇 시간 동안 디버깅을 즐겼다.크로스 플랫폼 아파치 모듈 개발 ap_retained_data_create/포스트 리드 구성 설정

내가 직면 한 문제는 Apache가 시작될 때 구성 파일을 두 번로드하므로 모듈 자체를 두 번로드한다는 것입니다. 일단 구성을 테스트하고 명령 구조체를 읽은 다음 서버의 빈 칸을 채우려면 다음을 읽으십시오. 이것은 일반적으로 어떤 문제도 발생하지 않지만 모든 클라이언트를 서비스하기 전에로드 할 때 모듈의 구성을로드하고 내 모듈의 요구 사항을 한 번만 구문 분석해야했습니다.

데이터베이스를 비롯한 여러 리소스를 사용하기 때문에 여러 번 실행하는 것이 좋지 않은 생각이 들었습니다. 특히 데이터베이스 서버에서 히트를 치는 것이 좋습니다.

온라인 설명서 ("Developer API 2.5")는 ap_retained_data_get 및 ap_retained_data_create를 사용하여 모듈을 언로드 한 상태에서 데이터를 유지하기 위해 이전 방법을 사용하는 대신 독자에게 보일 것이라고 말합니다. 가급적 테스트 단계를 통과 한 플래그를 다음 단계로 전달하는 것이 좋습니다.

여기 두통이있는 곳이 있습니다. 이것은 Windows에서 작동하는 방식이 아닙니다.

답변

2

Linux는 두 번 통과하지만 Windows는 네 번 통과합니다. 포스트 설정 읽어 후크에서이 방법을 사용

리눅스 작동 있지만 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 개의 패스가 있습니다. 거기에 귀하의 초기화가 여전히 두 번 실행됩니다.

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

가 좋아, 내가 바로 그 부분으로 수행하고 .... 일 듯 다음과 같이

내 다음 해결했다? 잘못된! 나는 리눅스 박스와 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

function fileExists는 파일이 있는지 판별하기 위해 다양한 apr_io 루틴을 감싸는 래퍼입니다. –