Bug 6690 - Give a caller a choice to call srand() by itself or let a SpamAssassin library do it
Summary: Give a caller a choice to call srand() by itself or let a SpamAssassin librar...
Status: RESOLVED FIXED
Alias: None
Product: Spamassassin
Classification: Unclassified
Component: Libraries (show other bugs)
Version: SVN Trunk (Latest Devel Version)
Hardware: All All
: P2 enhancement
Target Milestone: 3.4.0
Assignee: SpamAssassin Developer Mailing List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-03 17:39 UTC by Mark Martinec
Modified: 2017-12-04 20:49 UTC (History)
3 users (show)



Attachment Type Modified Status Actions Submitter/CLA Status
suggested change application/octet-stream None Mark Martinec [HasCLA]

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Martinec 2011-11-03 17:39:14 UTC
Created attachment 5006 [details]
suggested change

Here is a rather straightforward small change (two lines of code, plus docs)
which allows a caller (like spamd or amavisd) to call srand() soon after
forking, or let the library do it automatically as before. The change
retains compatibility with existing code and third party tools.

Here is a docs change, adding an option "skip_prng_reseeding" to a
list of options in a Mail::SpamAssassin->new() call:

+=item skip_prng_reseeding
+
+Mostly a compatibility measure. If this boolean setting is true, the
+SpamAssassin library will B<not> call srand() to reseed a pseudorandom
+number generator (PRNG). The srand() Perl function should be called during
+initialization of each child process, soon after forking. This can be done
+either by a caller (like spamd, or third party tools), or by the SpamAssassin
+library when it notices that its process id has changed. With versions 3.3.*
+and earlier the srand() was called unconditionally by the library - which may
+be undesired when a caller has already done it and wants to cherishly preserve
+entropy of a PRNG. Starting with 3.4.0 the caller has a choice. The default
+value of false (undef) maintains compatibility with former behaviour. This
+option should be set by a caller if it is calling srand() by itself on spawning
+child processes.

These are the two code changes in brief:

lib/Mail/SpamAssassin.pm:
-      srand;
+      srand  if !$self->{skip_prng_reseeding};

spamd/spamd.raw:
+    skip_prng_reseeding  => 1,  # let us do the reseeding by ourselves
[...]
+    srand;  # reseed pseudorandom number generator soon for each child process


The suggested change was prompted when I noticed that SpamAssassin.pm is
needlessly reshuffling the already shuffled perl random number generator,
which amavisd has already carefully reseeded by delegating it some of the
entropy it is maintaining.

The change also benefits spamd by calling srand() earlier, right after
forking. Previously the early initialization phases of a spamd child
process were all working with the same prng seed: a call to plugins
"spamd_child_init", reading use preferences, initializing bayes learner
object, (possibly more).
Comment 1 Kevin A. McGrail 2011-11-03 17:57:27 UTC
3.4.0 seems ideal for this type of change and this appears to conserve the entropy pool effectively and efficiently.

+1 here though I haven't patched and tested.  To be honest, the change was so trivial code-wise and so well explained, I didn't feel the need.
Comment 2 Darxus 2011-11-03 18:07:56 UTC
"cherishly" isn't a word.
Comment 3 Mark Martinec 2011-11-03 18:11:39 UTC
> +1 here though I haven't patched and tested.  To be honest, the change was so
> trivial code-wise and so well explained, I didn't feel the need.

Thanks, will commit.

> "cherishly" isn't a word.

Oops. Please suggest better phrasing.
Comment 4 Darxus 2011-11-03 18:18:44 UTC
(In reply to comment #3)
> > "cherishly" isn't a word.
> 
> Oops. Please suggest better phrasing.

"jealously" is the best thing I'm coming up with:
"vigilant in guarding a possession" - http://www.merriam-webster.com/dictionary/jealously

"carefully" would probably be more normal usage.
Comment 5 Kevin A. McGrail 2011-11-03 18:27:56 UTC
(In reply to comment #3)
> > +1 here though I haven't patched and tested.  To be honest, the change was so
> > trivial code-wise and so well explained, I didn't feel the need.
> 
> Thanks, will commit.
> 
> > "cherishly" isn't a word.
> 
> Oops. Please suggest better phrasing.

Here's my rip and shred of the docs.

If skip_prng_reseeding is set to true, the SpamAssassin library will B<not> call srand() to reseed a pseudo-random number generator (PRNG). The srand() Perl function should be called during initialization of each child process, soon after forking. 

Prior to version 3.4.0, calling srand() was handled by the SpamAssassin library.

This setting requires the caller to decide when to call srand().  This choice may be desired to preserve the entropy of a PRNG. The default value of skip_prng_reseeding is false if not defined to maintain backwards compatibility. 

This option should only be set by a caller if it calls srand() upon spawning child processes.  Unless you are certain you need it, leave this setting as false.

NOTE: The skip_prng_reseeding feature is implemented in spamd as of 3.4.0 which allows spamd to call srand() right after forking a child process.
Comment 6 Mark Martinec 2011-11-03 18:38:58 UTC
Great, thanks!

trunk:
  Bug 6690: Give a caller a choice to call srand() by itself
  or let a SpamAssassin library do it
Sending lib/Mail/SpamAssassin.pm
Sending spamd/spamd.raw
Committed revision 1197259.