pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

pkg/44704: spamass-milter livelock (patch)



>Number:         44704
>Category:       pkg
>Synopsis:       spamass-milter livelock (patch)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 09 16:35:00 +0000 2011
>Originator:     Juergen Hannken-Illjes
>Release:        NetBSD 5.0.2 / pkgsrc-2010Q4
>Organization:
        
>Environment:
        
        
System: NetBSD builder 5.0.2 NetBSD 5.0.2 (local.amd64) #1: Mon Feb 7 09:27:25 
MET 2011 
build@builder:/build/nbsd5/obj/obj.amd64/sys/arch/amd64/compile/local.amd64 
amd64
Architecture: x86_64
Machine: amd64
>Description:
For me spamass-milter under heavy load forks threads that livelock.  Looks
like both c++ string operations and malloc in the child after fork() and
before execvp() are bad things in a pthreaded application.

Attached patch resolves the problem for me by moving everything into the
parent and on the stack.
        
>How-To-Repeat:
Put spamass-milter under heavy load and see threads running with 100% cpu.
        
>Fix:
--- spamass-milter.cpp.orig     2011-03-06 14:03:18.000000000 +0100
+++ spamass-milter.cpp
@@ -1300,4 +1300,20 @@ SpamAssassin::~SpamAssassin()
 void SpamAssassin::Connect()
 {
+  int argc;
+  char *argv[100];
+  char spamc_user[64];
+
+  if (expandedrcpt.size() != 1) {
+    debug(D_RCPT, "%d recipients; spamc gets default username %s", 
(int)expandedrcpt.size(), defaultuser);
+    strlcpy(spamc_user, defaultuser, sizeof(spamc_user));
+  } else {
+    if (flag_full_email)
+      strlcpy(spamc_user, full_user().c_str(), sizeof(spamc_user)); 
+    else
+      strlcpy(spamc_user, local_user().c_str(), sizeof(spamc_user)); 
+    strlwr(spamc_user);
+    debug(D_RCPT, "spamc gets %s", spamc_user);
+  }
+
   // set up pipes for in- and output
   if (pipe(pipe_io[0]))
@@ -1333,31 +1349,10 @@ void SpamAssassin::Connect()
       // should be a little more secure
       // XXX arbitrary 100-argument max
-      int argc = 0;
-      char** argv = (char**) malloc(100*sizeof(char*));
+      argc = 0;
       argv[argc++] = SPAMC;
       if (flag_sniffuser) 
       {
         argv[argc++] = "-u";
-        if ( expandedrcpt.size() != 1 )
-        {
-          // More (or less?) than one recipient, so we pass the default
-          // username to SPAMC.  This way special rules can be defined for
-          // multi recipient messages.
-          debug(D_RCPT, "%d recipients; spamc gets default username %s", 
(int)expandedrcpt.size(), defaultuser);
-          argv[argc++] = defaultuser; 
-        } else
-        { 
-          // There is only 1 recipient so we pass the username
-          // (converted to lowercase) to SPAMC.  Don't worry about 
-          // freeing this memory as we're exec()ing anyhow.
-          if (flag_full_email)
-            argv[argc] = strlwr(strdup(full_user().c_str())); 
-          else
-            argv[argc] = strlwr(strdup(local_user().c_str())); 
-
-          debug(D_RCPT, "spamc gets %s", argv[argc]);
-         
-          argc++;
-        }
+        argv[argc++] = spamc_user;
       }
       if (spamdhost) 

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index