Hi everybody,

Short introduction:

We are a small company using Squid in our Unified Threat Management (UTM) series of products. I am working as a Backend developer and have tackled some problems with cross-compiling Squid in the past (see the unfortunately unanswered bug report at http://bugs.squid-cache.org/show_bug.cgi?id=4650).

The Problem:

We're using runit (http://smarden.org/runit/) to supervise squid 3.5.21 in "no_daemon"-mode (-N option).

Being interested in the SMP feature of squid we face the problem that it only works in daemon mode, which is inherently incompatible with runit supervising the service (would notice the process exiting and start it over and over again).

What are the reasons to tie the SMP feature so tightly to the daemon mode of squid? I played with the code and was able to alter the behavior and allow staying in foreground AND forking children that take the role of workers and coordinators etc.. I also managed to make the "master" process (the one staying in foreground) to react on a SIGTERM by signalling its children to shutdown. See the attached patch against the 3.5 branch of squid, which is not meant as a real contribution but just to show what I did.

I do acknowledge that I do not understand all implications of the changes I made, but in general, the program behaves as expected, with the slight exception that it runs into an exception if the configuration directive "workers 0" is given.

I noticed that in the squid 4 branch, the behavior again has slightly changed. What I get from the code in main.cc:watch_child is, that the "daemon" process stays alive until all its children terminate if the rather strangely named "opt_foreground" option is set. Additionally, the "master" process (the one created by the daemon's fork) processes signals and broadcasts those to its children.

Isn't it a rather small step from here to just prevent daemonizing and let the master process run in "real foreground"? That way, it seems to me that runit would not have any problems managing squid with standard signals and without changing the behavior of squid?

Am I missing something completely here? Is there some hidden problem that would break everything if instead of the "daemon-forking"-process, the master process itself would stay in the foreground? Or would it be possible?

Kind Regards,

Adnreas Weigel

--
Mit freundlichem Gruß / Best regards,

Andreas Weigel
UTM Backend Developer

Securepoint GmbH
Salzstrasse 1
D-21335 Lüneburg

https://www.securepoint.de

Tel.: +49(0)413124010
Fax: +49(0)4131240118

Geschäftsführer: Lutz Hausmann, Claudia Hausmann
Amtsgericht Lüneburg HRB 1776
USt.-ID-Nr.: DE 188 528 597

=== modified file 'src/main.cc'
--- src/main.cc	2016-09-23 15:28:42 +0000
+++ src/main.cc	2017-06-08 11:16:18 +0000
@@ -1457,7 +1457,7 @@
     RunRegisteredHere(RegisteredRunner::useConfig);
     enter_suid();
 
-    if (!opt_no_daemon && Config.workers > 0)
+    if (!opt_no_daemon || Config.workers > 0)
         watch_child(argv);
 
     if (opt_create_swap_dirs) {
@@ -1689,14 +1689,14 @@
         return;
 
     openlog(APP_SHORTNAME, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
-
-    if ((pid = fork()) < 0)
-        syslog(LOG_ALERT, "fork failed: %s", xstrerror());
-    else if (pid > 0)
-        exit(0);
-
-    if (setsid() < 0)
-        syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
+    if (!opt_no_daemon) {
+      if ((pid = fork()) < 0)
+          syslog(LOG_ALERT, "fork failed: %s", xstrerror());
+      else if (pid > 0)
+          exit(0);
+      if (setsid() < 0)
+          syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
+    }
 
     closelog();
 
@@ -1727,9 +1727,6 @@
         dup2(nullfd, 2);
     }
 
-    // handle shutdown notifications from kids
-    squid_signal(SIGUSR1, sig_shutdown, SA_RESTART);
-
     if (Config.workers > 128) {
         syslog(LOG_ALERT, "Suspiciously high workers value: %d",
                Config.workers);
@@ -1766,7 +1763,10 @@
         /* parent */
         openlog(APP_SHORTNAME, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
 
-        squid_signal(SIGINT, SIG_IGN, SA_RESTART);
+        // handle shutdown notifications from kids
+        squid_signal(SIGUSR1, sig_shutdown, SA_RESTART);
+        squid_signal(SIGINT, sig_shutdown, SA_RESTART);
+        squid_signal(SIGTERM, sig_shutdown, SA_RESTART);
 
 #if _SQUID_NEXT_
 

=== modified file 'src/tools.cc'
--- src/tools.cc	2016-12-16 12:18:27 +0000
+++ src/tools.cc	2017-06-08 10:02:21 +0000
@@ -438,6 +438,12 @@
 sig_shutdown(int sig)
 {
     shutting_down = 1;
+    if (IamMasterProcess()) {
+        for (int i = TheKids.count() - 1; i >= 0; --i) {
+          Kid &cur = TheKids.get(i);
+          kill(cur.getPid(), SIGINT);
+        }
+    }
 }
 
 const char *
@@ -661,7 +667,7 @@
 IamWorkerProcess()
 {
     // when there is only one process, it has to be the worker
-    if (opt_no_daemon || Config.workers == 0)
+    if (Config.workers == 0)
         return true;
 
     return TheProcessKind == pkWorker;
@@ -676,12 +682,14 @@
 bool
 InDaemonMode()
 {
-    return !opt_no_daemon && Config.workers > 0;
+    debugs(50, DBG_IMPORTANT, "opt_no_daemon=" << opt_no_daemon << " Config.workers=" << Config.workers); 
+    return !opt_no_daemon || Config.workers > 0;
 }
 
 bool
 UsingSmp()
 {
+    debugs(50, DBG_IMPORTANT, "InDaemonMode=" << InDaemonMode() << " NumberOfKids=" << NumberOfKids());
     return InDaemonMode() && NumberOfKids() > 1;
 }
 
@@ -695,7 +703,7 @@
 IamPrimaryProcess()
 {
     // when there is only one process, it has to be primary
-    if (opt_no_daemon || Config.workers == 0)
+    if (Config.workers == 0)
         return true;
 
     // when there is a master and worker process, the master delegates

_______________________________________________
squid-dev mailing list
squid-dev@lists.squid-cache.org
http://lists.squid-cache.org/listinfo/squid-dev

Reply via email to