Sorin! Thankyou so much, really appreciate your responses they are giving me a very good insight.
On Sun, May 26, 2013 at 12:59 AM, Sorin Manolache <sor...@gmail.com> wrote: > On 2013-05-25 15:22, Sindhi Sindhi wrote: > >> Hi, >> >> I see that the create_server_config callback is called twice for every >> Apache server startup. I want to do a lot of initialization in this >> callback and allocations in this function are meant to be long lived. And >> these buffers are very huge, so I want to ensure these initializations are >> done only once per server start. As of now I'm trying to do the following >> - >> > > There's not much you can do against the double-call of create_*_config. > > Here's a rough sketch of how apache works: > > create conf pool > create config objects for all modules and virtual hosts > read config > call pre_config callbacks > parse config > call post_config callbacks > > loop: > _clear the conf pool_ > create config objects for all modules and virtual hosts > read config > call pre_config callbacks > parse config > call post_config callbacks > create generation of children to handle the requests > wait on the generation to die > if the signal was to stop => exit the loop > else (i.e. reload conf) iterate > > So apache invokes create_*_config twice before starting to handle the > requests. But please note the following points: > > 1. The conf pool is cleared between the first and second call to > create_*_config. So if you allocated something in create_*_config when it > was called the first time you won't find it again when called the second > time. > > 2. A new server_rec is constructed each time apache calls "create config > objects for all modules and virtual hosts". This is why you don't find your > conf object with ap_get_module_config. > > 3. The create_*_config callbacks are called not only at the beginning, but > each time a new generation of children is spawned. An old generation is > sent the message to shut down when apache is sent a signal, either to stop > or to restart or to gracefully restart. Typically you want to reload the > conf because you changed it, so it's normal that apache reparses the conf. > > What you could do is to create the conf in the first call. You also store > it somewhere, let's say in a global variable. Then, in the second call, you > do not try to get it from the server_rec (as anyway the server_rec is brand > new and you would not find it there), but you get it from where you stored > it in the first call. > > So something like that: > > static MyConf *my_global_conf; > > void * > create_server_config() { > if (my_global_conf != NULL) > return my_global_conf; > my_global_conf = new MyConf; > return my_global_conf; > } > > Note that if you adopt this approach you should not allocate anything in > the pool that is passed to create_server_config because the pool is cleared > between invocations. > > Also there are two problems with this approach: > > 1. You'll have one single object for all virtual hosts. > 2. You cannot distinguish between the second call and subsequent calls. So > you cannot do a conf reload (a graceful restart) anymore because all > invocations of create_server_config except the first one will return the > old my_global_conf and will not react to changes in the configuration. So > you will be forced to do server restarts (as opposed to graceful restarts) > in order to load a new configuration. > > My advice is to live with the double invocation because you gain more than > you lose. It solves you the two problems mentioned above. You pay only by > waiting a little longer at startup. Even if apache did not call the > create_*_config functions twice before serving requests you would have to > live with several invocations of the create_*_config callbacks if you want > to support conf reloads. And conf reloads are very useful, you can reload > the conf without losing requests. > > In order not to leak, place a cleanup function in the list of cleanup > callbacks of the conf pool. For example: > > void * > create_server_config(apr_pool_**t *pconf, ...) { > MyConf *cnf = new MyConf; > apr_pool_cleanup_register(**pconf, cnf, &my_cleanup, > &apr_pool_cleanup_null); > return cnf; > } > > apr_status_t > my_cleanup(void *data) { > MyConf *cnf = reinterpret_cast<MyConf *>(data); > delete cnf; > return APR_SUCCESS; > } > > my_cleanup will be called when the conf pool is cleared, i.e. before each > new reparsing of the conf and creation of each new generation of children. > > Sorin > > > >> typedef struct >> { >> int bEnabled; // Enable or disable the module. >> MyFilterInit* myFilterInitObj; // A class that has methods to do all huge >> initializations >> bool serverConfigured; >> } MyFilterConfig; >> >> static int serverConfigHit = 0; >> >> static void* CreateServerConfig(apr_pool_t* pool, server_rec* virtServer) >> { >> MyFilterConfig *pExistingConfig = (MyFilterConfig *) >> ap_get_module_config (virtServer, &tag_filter_module); >> >> if (serverConfigHit == 0) { >> MyFilterConfig *pConfig = (MyFilterConfig *) apr_pcalloc (pool, sizeof >> *pConfig); >> pConfig->myFilterInitObj = new MyFilterInit(); // This does all the huge >> initializations >> serverConfigHit = serverConfigHit +1; >> return pConfig; >> } >> return pExistingConfig; >> } >> >> But I see an issue here. The second time when CreateServerConfig is >> called, >> 1. pExistingConfig is not having the address which was set during the >> first >> call to CreateServerConfig >> 2. serverConfigHit is zero. >> >> Which means when CreateServerConfig was called first time, all the >> initializations I made is not recorded by the server. Which means all the >> allocations I made in the first call using malloc/new will result in a >> memory leak. >> >> Kindly advice how do I ensure that my initializations are performed only >> once. >> >> Thanks >> >> >