Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x0vncserver: Add support for systemd socket activation #1716

Merged

Conversation

MikeLooijmans
Copy link
Contributor

systemd can pass in sockets as file descriptors 3 and beyond. Allows the server to use socket activation.

@CendioOssman
Copy link
Member

Nice. Socket activation is something we've mostly thought about for vncserver. The use case for x0vncserver is not as apparent, as it needs an existing X11 server that it can talk to.

Would you mind describing how you envision this to be used?

@CendioOssman CendioOssman added the enhancement New feature or request label Jan 12, 2024
@@ -21,6 +21,13 @@ target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/unix)
target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/common)
target_link_libraries(x0vncserver tx rfb network rdr unixcommon)

# check for systemd support (socket activation)
pkg_check_modules(LIBSYSTEMD libsystemd)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try to put all checks in the top CMakeLists.txt, to make it easier to see TigerVNC's dependencies.

On that note, do you think you could add this as an optional dependency to BUILDING.txt?


for (int i = 0; i < count; ++i) {
/* systemd sockets start at FD 3 */
listeners->push_back(new TcpListener(3 + i));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a SD_LISTEN_FDS_START constant. Can't we use that to make things more clear?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The systemd docs said "3", a constant is better than a magic number.

static int createSystemdListeners(std::list<SocketListener*> *listeners)
{
#ifdef HAVE_SYSTEMD_H
int count = sd_listen_fds(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's best to check for errors explicit. Less risk for future bugs.

if (rfbunixpath.getValueStr()[0] != '\0') {
if (createSystemdListeners(&listeners)) {
vlog.info("Listening on systemd sockets");
} else if (rfbunixpath.getValueStr()[0] != '\0') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The else seems improper here. Let's respect all the options given.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using systemd, ALL listening sockets will be passed through filedescriptors. The server shouldn't attempt to open any further sockets on its own. So this flow is on purpose. Otherwise you'd be obligated to explicitly disable the other (default) sockets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, the proposed change is not succeeding. It disables Unix sockets, which are already disabled by default. But the TCP socket will still start.

I still don't think we should prevent people from listening to both. We've had issues with such black-and-white models before. But I can agree that it might be sensible to have different defaults if it's systemd activated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were some changes between this version and the one I tested with, I've updated the code to handle things as intended.

@MikeLooijmans
Copy link
Contributor Author

Nice. Socket activation is something we've mostly thought about for vncserver. The use case for x0vncserver is not as apparent, as it needs an existing X11 server that it can talk to.

Would you mind describing how you envision this to be used?

Add a a socket and service file, e.g.

$ cat x0vncserver.service

[Unit]
Description=Remote desktop service (VNC) for :0 display
Requires=display-manager.service
After=display-manager.service

[Service]
Type=simple
ExecStart=x0vncserver -display :0 -rfbauth /etc/vncpasswd -MaxDisconnectionTime 3 -ClientWaitTimeMillis 3000

$ cat x0vncserver.socket

[Socket]
ListenStream=5900

[Install]
WantedBy=sockets.target

Connecting to port 5900 will automatically start the server, and multiple clients can connect. 3 seconds after the last client disconnects, the server will shut down. When a new client connects, systemd will start a new instance of the server.

This allows one to always have a VNC server on "standby", but it doesn't consume any resources (apart from the listening socket) when not in use.

@CendioOssman
Copy link
Member

Thanks. That makes it clear how things can be set up. Perhaps that should be added to the man page?

I'm still not clear how the whole system is supposed to work, though. How have you made sure there is a useful X server on :0? And that x0vncserver is authorized to talk to it?

Is it the display manager that's on :0? What happens once you log in at that point? Won't the desktop be started at :1?

@MikeLooijmans
Copy link
Contributor Author

Our particular use case is an embedded system. Since that only every runs one desktop with one user, we can get away with hardcoding the DISPLAY. Other people with other use cases may have to write their own solutions to all the problems you're mentioning.

My focus here is to get systemd support into the server, because I think it'd be useful to others as well, and upstreaming it will also avoid having to maintain it locally.

I'm willing to spend a reasonable bit of effort to get it into the project, but the response I'm getting so far isn't very encouraging.

@MikeLooijmans MikeLooijmans force-pushed the systemd-socket-activation branch from 8173602 to 50147aa Compare January 12, 2024 14:59
systemd can pass in sockets as file descriptors 3 and beyond. Allows
the server to use socket activation.

When triggered by systemd, no other listening sockets (e.g. rfbport) will
be activated.

Signed-off-by: Mike Looijmans <[email protected]>
@MikeLooijmans MikeLooijmans force-pushed the systemd-socket-activation branch from 50147aa to fdd429c Compare January 12, 2024 15:04
@CendioOssman
Copy link
Member

We are definitely open to merging this. But please keep in mind that TigerVNC is used by a lot of people. So we need to be careful to balance the needs of all our users. Which means a feature may need more polish than was needed in its initial use case.

Copy link
Member

@CendioOssman CendioOssman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be mostly done. Let me have a look at some compatibility tweaks, and then I can get this merged.

@CendioOssman CendioOssman merged commit fdd429c into TigerVNC:master Jan 24, 2024
12 checks passed
@MikeLooijmans MikeLooijmans deleted the systemd-socket-activation branch January 24, 2024 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants