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

Bug#742666: cups-daemon: No Upstart support



Cameron, please also make sure that your Upstart support works with
socket activation, as it does with the current Ubuntu package. Please
integrate the two patches introduced for that in the Ubuntu package
(attached) in the Debian package. Also modify the Upstart jobs so that
the CUPS daemon starts socket-activated (via port 631 and
/var/run/cups/cups.sock) but CUPS also starts when a USB printer is
plugged/unplugged or on boot when printers are shared or jobs in the queues.

This way we can use CUPS on mobile systems (like Ubuntu Touch) or simply
save battery power on laptops.

   Till
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -1683,6 +1683,13 @@
   if (_httpAddrPort(&(lis->address)) == 443)
     lis->encryption = HTTP_ENCRYPT_ALWAYS;
 #  endif /* HAVE_SSL */
+
+  /* As we are started on-demand, stop on idle */
+  if (!ExitOnIdleTimeout)
+    ExitOnIdleTimeout = 30;
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "As we are starting on-demand (socket-triggered), activate exit-on-idle mode, timeout: %d seconds.",
+                      ExitOnIdleTimeout);
+
 }
 
 /*
Description: CUPS Upstart socket activation:
 Important to note:
 - Run by default in foreground (-f), not Foreground (-F). With -F CUPS
 closes all inherited file descriptors, which is not needed under
 upstart since it does that on our behalf, furthermore closing passed
 socket activation descriptors prevents us from using socket
 activation.
 - Force foreground (-f) mode if environment suggests that we are Upstart
 socket activated (similar to "-l" flag for launchd).
 - Initialize addrlen to sizeof(addr) to make getsockname() work.
 - Correct environment variable name used to check event type
 - Get UPSTART_FDS simply with atoi()
 - Perform explicit return code checking from getsockname function call
Author: Till Kamppeter <till.kamppeter@gmail.com>,
 Dimitri John Ledkov <xnox@ubuntu.com>
Bug: https://bugs.launchpad.net/ubuntu/+source/cups/+bug/1276713
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -26,6 +26,8 @@
  *   launchd_checkin()     - Check-in with launchd and collect the listening
  *                           fds.
  *   launchd_checkout()    - Update the launchd KeepAlive file as needed.
+ *   upstart_checkin()     - Check-in with Upstart and collect the
+ *                           listening fds.
  *   parent_handler()      - Catch USR1/CHLD signals...
  *   process_children()    - Process all dead children...
  *   select_timeout()      - Calculate the select timeout value.
@@ -83,6 +85,7 @@
 static void		launchd_checkin(void);
 static void		launchd_checkout(void);
 #endif /* HAVE_LAUNCHD */
+static void		upstart_checkin(void);
 static void		parent_handler(int sig);
 static void		process_children(void);
 static void		sigchld_handler(int sig);
@@ -320,6 +323,14 @@
       usage(1);
     }
 
+  /* force non-disconnecting foreground mode upon upstart socket
+   * activation, as otherwise all fd's are closed before we get to use
+   * them */
+  if (getenv("UPSTART_FDS"))
+  {
+    fg      = 1;
+  }
+
   if (!ConfigurationFile)
     cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
 
@@ -573,6 +584,11 @@
 #endif /* HAVE_LAUNCHD */
 
  /*
+  * If we were started by Upstart get the listen sockets file descriptors...
+  */
+  upstart_checkin();
+
+ /*
   * Startup the server...
   */
 
@@ -761,6 +777,13 @@
 #endif /* HAVE_LAUNCHD */
 
        /*
+        * If we were started by Upstart get the listen sockets file
+	* descriptors...
+        */
+
+        upstart_checkin();
+
+       /*
         * Startup the server...
         */
 
@@ -1509,6 +1532,93 @@
 }
 #endif /* HAVE_LAUNCHD */
 
+static void
+upstart_checkin(void)
+{
+  /*
+   * Example socket event environment:
+   *
+   * UPSTART_INSTANCE=
+   * PORT=34568
+   * PROTO=inet
+   * UPSTART_JOB=foo5
+   * UPSTART_FDS=43
+   * UPSTART_EVENTS=socket
+   * ADDR=127.0.0.1
+   *
+   */
+  int fd = 0;
+  const char *e;
+  http_addr_t addr;
+  socklen_t addrlen = sizeof(addr);
+  cupsd_listener_t *lis;
+  char s[256];
+
+  if (!(e = getenv("UPSTART_EVENTS")))
+    return;
+
+  if (strcasecmp(e, "socket"))
+    return;
+
+  if (!(e = getenv("UPSTART_FDS")))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+		    "upstart_checkin: We got started via Upstart socket event but no environment variable UPSTART_FDS is not set");
+    return;
+  }
+
+  fd = atoi(e);
+
+  if (getsockname(fd, (struct sockaddr*) &addr, &addrlen) < 0)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+		    "upstart_checkin: Unable to get local address - %s",
+		    strerror(errno));
+    return;
+  }
+
+ /*
+  * Try to match the systemd socket address to one of the listeners...
+  */
+
+  for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+       lis;
+       lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+    if (httpAddrEqual(&lis->address, &addr))
+      break;
+
+  if (lis)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+		    "upstart_checkin: Matched existing listener %s with fd %d...",
+		    httpAddrString(&(lis->address), s, sizeof(s)), fd);
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+		    "upstart_checkin: Adding new listener %s with fd %d...",
+		    httpAddrString(&addr, s, sizeof(s)), fd);
+
+    if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+		      "upstart_checkin: Unable to allocate listener - "
+		      "%s.", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+
+    cupsArrayAdd(Listeners, lis);
+
+    memcpy(&lis->address, &addr, sizeof(lis->address));
+  }
+
+  lis->fd = fd;
+
+#  ifdef HAVE_SSL
+  if (_httpAddrPort(&(lis->address)) == 443)
+    lis->encryption = HTTP_ENCRYPT_ALWAYS;
+#  endif /* HAVE_SSL */
+}
 
 /*
  * 'parent_handler()' - Catch USR1/CHLD signals...

Reply to: