Peter J. Holzer wrote:
On 2007-12-03 21:56:48 +0100, Niklas Therning wrote:
Matt Sergeant wrote:
On 3-Dec-07, at 2:45 PM, Niklas Therning wrote:
I'm writing a qpsmtpd plugin for our custom spam filter. The plugin
reads a couple of custom configuration files at startup. The config
files may change at any time and I would like my plugin to pick up
those changes automatically.
Now, I've tried to periodically check the timestamp of the files in
my plugin and reload them if necessary but never got that to work.
I've posted on this list before about that problem but got no replies
(http://www.nntp.perl.org/group/perl.qpsmtpd/2007/11/msg7501.html).
You are using the wrong hook: connect is executed after the fork, so it
will only affect the child. You need to use pre-connect. See below.
That would explain why my changes don't stick! Thanks, I'll try to use
that hook instead.
Is there any way I could tell a running qpsmtpd-forkserver instance
(version 0.32) to reload its plugins without having to restart the
process? I guess it would work to restart it entirely but it seems to
me that it would be better to just have it reload the plugins so that
any running connections don't have to be killed.
Under forkserver, config information should be loaded by each child
anyway.
Or do you mean reloading the entire plugin? That's another matter...
And something I'm working on as a background task.
Thanks for answering!
I read the config files in my plugin's init(). Do you mean that
forkserver creates a new plugin instance (new $self) and calls init()
each time it forks?
No. It calls init only once. What he means is that the plugin should
reread the config for each connection, and hence not in init.
I would like to avoid a situation where the config
files are read for every new connection.
A good place for reading the config is the "pre-connection" hook. This
is executed after a connection is accepted but before the child process
handling the connection is forked. So you can stat the config file in
this hook and reread it if it has been changed. The changes will then be
visible in this and all subsequent connections (until it is changed
again).
For an example, see my aliases_check plugin in the contrib directory:
http://svn.perl.org/viewcvs/qpsmtpd/contrib/hjp/aliases/aliases_check?view=markup&rev=687
About half of what my plugin does is to read an alias file and then on
each connection it expands the aliases. Using your plugin I could
probably throw away most of my code! :-) Does aliases_check change the
recipients in the transaction so that the next plugin sees the real
recipients after alias expansion? Using my limited Perl knowledge
reading your code tells me that it doesn't change the transaction but
adds a note with the expanded recipients. Am I right?
I think I mean reloading the entire plugin.
From your description in the first paragraph that doesn't seem to be the
case. You only want to reload the configuration, not the code.
But just in case you really want to change the code on the fly:
I Googled and found some references to qpsmtpd-highperf which seems to
be able to do what I'm looking for (see
http://www.nntp.perl.org/group/perl.qpsmtpd/2006/05/msg5130.html).
I see nothing in that mail which suggests that ability (it may be in the
patch, I haven't looked at that).
From that mail:
"Difference in relation to <qpsmtpd-forkserver>:
- pre-fork children
- reuse child
- renice of parent to ensure reaper and re-spawn of children
- reload option to graceful reinitialize plugins"
Judging from that conversation this patch has been applied and renamed
qpstmpd-prefork. I had a look at the qpsmtpd-prefork script and it seems
to be able to reload the plugins if I send SIGHUP to it.
I don't think this will work: Qpsmtpd::load_plugins checks if the
plugins are already loaded and does nothing if that's the case.
From qpsmtpd-prefork in current trunk:
# Hup handler
$SIG{HUP} = sub {
# reload qpmstpd plugins
$qpsmtpd->load_plugins;
kill 'HUP' => keys %children;
info("reload daemon requested");
};
So you mean that this code actually only loads new plugins and doesn't
reload already loaded ones?
Thanks for all your answers! I will go back to my first approach and use
the pre_connection hook instead as you suggested and see if that solves
my initial problems.
/Niklas