Bug 60560 - Support systemd/inetd style socket activation
Summary: Support systemd/inetd style socket activation
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Connectors (show other bugs)
Version: 8.5.9
Hardware: PC All
: P2 enhancement (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-01-07 16:43 UTC by Thomas Meyer
Modified: 2018-06-29 21:24 UTC (History)
1 user (show)



Attachments
propsed patch (1.93 KB, patch)
2017-01-07 16:43 UTC, Thomas Meyer
Details | Diff
updated patch with documentation (4.58 KB, text/plain)
2017-03-18 12:31 UTC, Thomas Meyer
Details
updated patch with documentation (4.29 KB, patch)
2017-05-05 08:00 UTC, Thomas Meyer
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Meyer 2017-01-07 16:43:42 UTC
Created attachment 34600 [details]
propsed patch

Use the provided channel from systemd/inetd.
systemd will bind to the socket and forward the channel to tomcat, so tomcat can run as non-root user on port 80.

For this to work correctly tomcat must be started directly as java program from systemd unit file and not from intermediate script for channel passing to work correctly.
Comment 1 Mark Thomas 2017-01-31 09:57:49 UTC
The patch assumes that there is only a single NIO endpoint. That assumption is not valid. The patch needs to handle the multiple end-point case. That in turn raises the question of how useful this feature is since it appears only to be able to handle a single channel.

This feature is not compatible with NIO2. Nor is it compatible with APR/native.

The patch needs to be extended to enable configuration to be used to specify which connector should use the inherited channel. I'd suggest either a new configuration option called "useInheritedChannel" or a special value for "address". My preference would be for a new option. It should be specific to NIO.

Documentation is also required.
Comment 2 Remy Maucherat 2017-01-31 10:43:28 UTC
About NIO2, this doesn't work as the code in System.inheritableChannel uses the NIO API directly, but the API itself is "compatible" (an AsynchronousServerSocketChannel will implement Channel). Odd that this was never added (as a separate equivalent method). I think they forgot about this stuff (I had no idea it existed personally).
Comment 3 Thomas Meyer 2017-02-03 20:03:26 UTC
Updated patch here: http://static.217.14.99.88.clients.your-server.de/401

Where can I find the source of the documentation. It seems to be in an different repository?!
Comment 4 Mark Thomas 2017-03-03 12:26:46 UTC
Documentation is in trunk/webapps/docs
Comment 5 Thomas Meyer 2017-03-18 12:31:09 UTC
Created attachment 34844 [details]
updated patch with documentation
Comment 6 Thomas Meyer 2017-05-05 08:00:17 UTC
Created attachment 34982 [details]
updated patch with documentation
Comment 7 Coty Sutherland 2018-01-19 19:13:32 UTC
Comments from a review of the latest provided patch:

* Your patch adds an unnecessary space before the TimeUnit import in NioEndpoint
* There is a typo, 'automatically', in http.xml
* The useInheritedChannel documentation addition in http.xml specifies type (boolean) which is inconsistent with other (bool) attrs
* If you specify useInheritedChannel on a Connector it shouldn't fall back to the default behavior when starting without an OS provided socket. If you specifically designate that tomcat should use an OS socket, then it should fail to start the Connector (like the behavior that causes an SSL Connector to fail to start when it can't find the keystore).
* If you're borrowing a socket from the OS for tomcat to use (by skipping the bind), then you shouldn't be closing the socket in NioEndpoint.unbind().

After applying this patch the behavior seems to work (mostly, systemd is behaving a bit odd, but that's not tomcat's fault), but there's something that may be confusing for users: the thread name (i.e. Starting ProtocolHandler ["http-nio-8080"]). If you specify useInheritedChannel on the Connector then you're no longer using the specified port. We should probably address that somehow.
Comment 8 Coty Sutherland 2018-01-19 19:18:07 UTC
And just individuals interested in testing this, you need the following new socket descriptor and modification to the systemd service unit:

Create a socket in /etc/systemd/system/tomcat.socket (this one opens a socket bound to localhost on port 80):

~~~
[Unit]
Description=Socket for Tomcat
PartOf=tomcat.service

[Socket]
ListenStream=127.0.0.1:80

[Install]
WantedBy=sockets.target
~~~

Then add `Requires=tomcat.socket` to the [Unit] section of your tomcat systemd service unit and `StandardInput=socket` to the [Service] section.

After adding those, starting the service (systemctl start tomcat) will open the socket and pass that through to tomcat. You can also start the tomcat service on the first request to localhost:80, but you have to start the socket first (systemctl start tomcat.socket).
Comment 9 Remy Maucherat 2018-06-29 21:24:34 UTC
This will be available in 9.0.11+ and 8.5.33+. Thanks for the patch, ideas and testing.