I've got a "reality check" question for people to see that I'm not missing something obvious with our Apache::Reload mod_perl setup.
 
We've recently install Apache::Reload at our site in production and it's working great. In what is probably not the best 'software engineering' style, we've been known to upload several small patches in a single day and used to have to do short restarts to integrate the new code. We now use Apache::Reload instead. Rather than putting 'use Apache::Reload' in each of our modules, I've created a touch file, which after looking through the Apache::Reload code, I noted that you could put a list of modules into it which would be reloaded.
 
On top of this, we use mod_accel as a front end to our mod_perl backend. This combination seems to work great as well for anyone curious.
 
The question I had regards where to put the 'Apache::Reload' directive. The documentation suggests something like:
 
  PerlInitHandler Apache::Reload
  PerlSetVar ReloadAll Off
  PerlSetVar ReloadTouchFile /tmp/reload_modules
 
The problem I see in a production machine is that each child process will see this on the next request, and attempt to reload it's modules. At that point, you'll loose the shared memory the modules use between child processes.
 
On top of this, the parent process will never get this, so it will never reload modules in the parent. The next time a new child is forked, on the first request it receives it will again attempt to reload the changed modules. Is this correct? Or am I missing something?
 
The alternative I've used is this:
 
  PerlRestartHandler Apache::Reload
  PerlSetVar ReloadAll Off
  PerlSetVar ReloadTouchFile /tmp/reload_modules
 
Then when I've uploaded any changes, I touch the change file, and do an 'apachectl graceful' to restart the backend. I think this works nicely because:
 
1) The mod_accel front end will buffer any long file uploads, and any long file downloads. So the actual length of connections from the frontend to the backend is only as long as it takes to process the request and tunnel the data betwen the front->back or back->front. Thus the 'graceful' restart only ever takes a few seconds, and no connections are ever lost, only blocked for a few seconds at the most (the length of the longest request to process).
2) Doing it in the restart handler means that the parent process reloads the modules, and all the newly forked children have shared copies.
 
Can anyone tell me if I'm missing something here?
 
Rob
 

Reply via email to