upstart socket activation for cups

Bug #1276713 reported by Dimitri John Ledkov
16
This bug affects 2 people
Affects Status Importance Assigned to Milestone
upstart
Invalid
Undecided
Dimitri John Ledkov
cups (Ubuntu)
Fix Released
Undecided
Till Kamppeter

Bug Description

tkamppeter and I, worked on porting cups to use socket activation. There were a few issues:

cups by default, binds to "localhost:631" it does it by resolving localhost and then binding to all IP address there were returned, so by default it does ::1 and 127.0.0.1.

Once that configuration option is established a list of sockets is generated, we've modified initialisation to look at UPSTART_FDS (similar to uwsgi) and replace matching sockets passed to us into the list.

This appears to work fine, apart from it appeared as if sockets passed by upstart to us are bound to 0.0.0.0 regardless of the configuration (or so getsockname tells cups).

Secondly since upstart only gives us one socket, i opted to modify cups config to explicitely listen on ipv4 127.0.0.1 and disabled the unix domain socket option, such that clients socket activate cups and communicate via that socket.

After doing all of the above, we noticed that although cups is started and is managed by upstart and cups logs indicate that it apparently has resumed accepting connections.... but there is already a client connection / request pending which activated cups in the first place. After inspecting netstat it was apparent that connection has buffered/unprocessed packets still waiting for a reply. Eventually a client that socket activated cups timesout and exits, and subsequent connections work correctly. I believe that we didn't increment "client connection count" to one in CUPS state-machine or some such.

Following example code within upstart which performs lauchd socket activation was not useful either, as that code path is clearly buggy, since it incorrectly checks for error/return codes of getsockname.

I'll attach the state of our patch work to this bug report.

I dislike, how "accepting connections" is paused/resumed and how cups does dns resolution and thus listens on more connections than configured to. I think best way to proceed is to instead investigate and patch unix domain socket activation for cups, as hopefully that is slightly more reliable from the upstart-socket-bridge.

The bug of not processing the first connection, i presume, is in cups codebase - unless we are required to replay the messages.

Tags: patch
Revision history for this message
Dimitri John Ledkov (xnox) wrote :
Changed in upstart:
status: New → Confirmed
Changed in cups (Ubuntu):
status: New → Confirmed
Changed in upstart:
assignee: nobody → Dimitri John Ledkov (xnox)
Changed in cups (Ubuntu):
assignee: nobody → Till Kamppeter (till-kamppeter)
tags: added: patch
Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

Committed cups 1.7.1-5 to the Debian GIT repository of CUPS. This contains the changes on cupsd to support triggering the daemon by the Upstart socket bridge and in addition changes for cupsd to terminate if it gets idle (no jobs, no shared printers). The package will appear in Trusty as soon as it is uploaded to Debian and then auto-synced to Ubuntu.

Changed in cups (Ubuntu):
status: Confirmed → In Progress
Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

Note that the package does not contain the Upstart config file changes of the debdiff attached to this bug, to keep user's systems working.

Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

Uploaded cups 1.7.1-4ubuntu1 with the changes needed on CUPS to Trusty.

Changed in cups (Ubuntu):
status: In Progress → Fix Committed
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package cups - 1.7.1-4ubuntu1

---------------
cups (1.7.1-4ubuntu1) trusty; urgency=low

  * cupsd-upstart-support.patch: Allow starting cupsd socket-triggered
    through Upstart, for on-demand starting to save resources (especially
    on mobile devices, LP: #1276713).
  * cupsd-exit-on-idle.patch: Add mode to let cupsd terminate when it is idle,
    also for running CUPS on-demand. If the mode is activated, either by
    ExitOnIdleTimeout=TIMEOUT in cupsd.conf, by "-x TIMEOUT" on the cupsd
    command line or by setting the env variable CUPSD_EXIT_ON_IDLE_TIMEOUT=
    TIMEOUT (With TIMEOUT in all theree cases the idle timeout in seconds,
    0 turning off the feature, off by default), cupsd terminates when it
    is idle (no jobs, no shared printers) for the given timeout.
  * cupsd-exit-on-idle-upstart.patch: Set idle timeout of cupsd to 30 sec
    if CUPS is started socket-triggered by Upstart and the timeout is not
    explicitly set (LP: #1276713).
  * airprint-support.patch, pidfile.patch,
    do-not-broadcast-with-hostnames.patch, confdirperms.patch,
    log-debug-history-nearly-unlimited.patch,
    cupsd-set-default-for-SyncOnClose-to-Yes.patch: Refreshed with quilt.
 -- Till Kamppeter <email address hidden> Fri, 14 Feb 2014 17:08:01 +0100

Changed in cups (Ubuntu):
status: Fix Committed → Fix Released
Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

To get the on-demand daemon use concept described in the Blueprint

https://blueprints.launchpad.net/ubuntu/+spec/client-1305-printing-stack-with-mobile-in-mind

working, we need working socket activation in Upstart as this is the most convenient and well tested (on Mac OS X this is standard) way to run CUPS on-demand.

Without fixing Upstart we would need to add a keep-running-while-avahi-daemon-is-present mode to cupsd (avahi-daemon is present while the print dialog is open on mobile) which would be awkward and probably not accepted upstream.

So it is very important to fix Upstart. Can someone mark this bug as high priority?

Changed in upstart:
status: Confirmed → Invalid
Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

Remaining problems fixed in cups 1.7.1-5ubuntu6. Thank you, xnox, for the patch!

Revision history for this message
Cameron Norman (cameronnemo) wrote :

Three comments about this:

* can the $UPSTART_FDS still be gotten even if $UPSTART_EVENTS is not socket? That way we could add some other start event and still get socket activation.

* If so, would it be a good idea to add a "or usb-device-added ID_MODEL=USB_Printer" to the start on, to make the delay of CUPS starting even more invisible to the user? (WARNING: have not confirmed that USB_Printer ID_MODEL can be relied upon consistently, that is just what I got in upstart monitor when I plugged in my printer).

* Finally, I think the default exit on idle should be more than 30 seconds; more like a minute, maybe 1:30. This would have big benefits to the UX with a tiny impact on battery life IMO.

Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

Cameron, puttin 1:30 min as idle timeout is no problem, for your other questions Dimitri will probably have an answer.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

* can the $UPSTART_FDS still be gotten even if $UPSTART_EVENTS is not socket? That way we could add some other start event and still get socket activation.

No, it cannot. UPSTART_FDS is a variable provided by an event type socket only.

* "or usb-device-added ID_MODEL=USB_Printer"

That could be added, and I think that would be beneficial.

* Finally, I think the default exit on idle should be more than 30 seconds;

I have no opinion. Imho cups starts so quick that it doesn't matter how quickly it goes to idle. Do we have any data w.r.t. how long it should be? E.g. why 1m30s and not 5m17s ? As far as I know, the current 30s was just arbitrary selected value.

Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

For the timeout it is most important that it is well more than the 10 seconds which is the check interval of cups-daemon for removing a print queue which is scheduled for removal but still in use. If CUPS starts up quickly enough, the 30 seconds should be OK, but best is trying out.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.