Skip to content
This repository has been archived by the owner on Sep 15, 2021. It is now read-only.

Allow reloading config without restarting the daemon #52

Closed
wants to merge 4 commits into from
Closed

Allow reloading config without restarting the daemon #52

wants to merge 4 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Oct 3, 2019

Closes #13. There are two supported ways to do it:

  1. Run the command kanshictl reload
  2. Send the process a SIGHUP

The varlink protocol is used, so that should make it easy to add more commands to kanshictl.

@ghost
Copy link
Author

ghost commented Oct 13, 2019

This is broken in CI because varlink is not in the AUR. It can be added as a subproject if we want to fix that in the meantime.

@emersion
Copy link
Owner

Added libvarlink to the AUR.

@ghost
Copy link
Author

ghost commented Oct 26, 2019

Looks good on CI, ready for review

Copy link
Owner

@emersion emersion left a comment

Choose a reason for hiding this comment

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

Here's a first round of comments. Thanks for your work and sorry for the long delay! I'm excited for this new feature :)

If it's fine by you, I'd prefer to merge the varlink support first and then the signal stuff in another review round.

include/ipc.h Outdated Show resolved Hide resolved
include/kanshi.h Outdated Show resolved Hide resolved
main.c Outdated Show resolved Hide resolved
main.c Outdated Show resolved Hide resolved
main.c Outdated Show resolved Hide resolved
ctl.c Outdated Show resolved Hide resolved
ctl.c Outdated Show resolved Hide resolved
kanshictl.1.scd Outdated Show resolved Hide resolved
meson.build Outdated Show resolved Hide resolved
meson.build Outdated Show resolved Hide resolved
@zsugabubus
Copy link

Change my mind, but is it really necessary to add such a bloat? Config reload (that you almost never need) and profile switching could be (easily) done in other ways too.

The varlink protocol is used, so that should make it easy to add more commands to kanshictl.

What other commands you want to add (don't misunderstand!) to a sh*tty program which only task is to load preset configurations?

@ghost
Copy link
Author

ghost commented Jan 17, 2020

@emersion Sorry for the delay, no time to work on Wayland stuff recently, but I will be getting to this soon.

@zsugabubus The other use case for IPC is documented in #10. The original implementation used a simple custom IPC, but that was not flexible and was going to be even more code to integrate it well. My personal use case for this is in cyclopsian/wdisplays#4.

@zsugabubus
Copy link

Why not just kill and restart?

@ghost
Copy link
Author

ghost commented Jan 18, 2020

Without an IPC mechanism there is no way to find the right process. Doing killall kanshi is not safe.

@ghost
Copy link
Author

ghost commented Jan 18, 2020

It should also be noted that in general, procfs + Unix signals are not appropriate for IPC. See these articles for some more info on the problem and why either a workaround or a kernel-level solution is needed: https://lwn.net/Articles/773459/ https://lwn.net/Articles/794707/

@zsugabubus
Copy link

zsugabubus commented Jan 18, 2020

Doing killall kanshi is not safe.

I don't get it. What do you mean by unsafe? Even if you have parallel Wayland session with the same user, you could use:

  • PID files,
  • add a simple signal handler,
  • wrap it inside a (systemd) service.

They would just about 10-15 LOC instead of adding a noname library(*) as dependency plus more hundred lines. For a task that you do only once... okay... twice in your lifetime.

*: Dunno if anybody have tried to build it at all but meson fails with an error.

It should also be noted that in general, procfs + Unix signals are not appropriate for IPC. See these articles for some more info on the problem [...]

Do you think it is really relevant in our case?

@ghost
Copy link
Author

ghost commented Jan 18, 2020

The original implementation did that and there were issues so I scrapped it. A daemon should never ever manage its own PID file. If the program is killed then the PID file will stick around and could potentially point to the wrong process. We could only use systemd if it was running in user mode, which not everybody does. Also systemd is optional in wlroots/sway so we want to retain that. Even with systemd there is still no reasonable way to use unix signals for IPC and have it work in all cases, read those articles for more information about this.

I encourage you to read more about varlink, it supports a very simple process-to-process IPC. Using pid files and signals is not a realistic alternative for IPC. The only realistic alternative is dbus which I would like to avoid if we can because that would be unnecessary; we don't need another daemon to handle multicast. If you're having a problem with building varlink, please confirm that it is a bug in the package and not a missing meson dependency. Then file an issue with varlink if appropriate.

@zsugabubus
Copy link

zsugabubus commented Jan 18, 2020

I would like to stay constructive.

Of course, everything is true what you write. I just saw a simple task, but the solution is an external library (installing, updating, what if abandoned), JSON and more thousands(!) LOC.

When you want to change your background you restart swaybg; when you want to update your sway config you restart it. For me it would be totally okay if kanshi would work the same (although it's not only for sway).

In addition, I have never met a program that had a special ability for rereading the configuration. (Maybe not without reason?)

If the program is killed then the PID file will stick around and could potentially point to the wrong process

Of course. Add a lockfile. With this, it's way more race-condition free than varlink is now.

I encourage you to read more about varlink, it supports a very simple process-to-process IPC.

It's surely a nice thing for a process that indent to handle more than one, parameterless command. (Switching doesn't need to be an IPC command. See my PR how I imagined it could work.)

The only realistic alternative is d[...]

Don't continue. 😄

Even with systemd there is still no reasonable way to use unix signals for IPC and have it work in all cases

In my service-like (systemd...) version you don't need signals anymore. You just restart the right instance of the service to reload the config.


It would be good to hear what @emersion thinks about it. But I guess he is okay with it, otherwise he wouldn't add it to AUR...

I think I stop trying convincing you. 😭

@ghost
Copy link
Author

ghost commented Jan 18, 2020

Sway is a bad example. It also includes JSON and many thousand of lines of code to implement the i3 IPC protocol over a socket. When you type swaymsg reload that does not kill the program, it sends an IPC message to re-read the config. Your service manager can track PIDs of its child processes itself which is why it's safe to use it to send signals, although this is not totally race-free unless it uses pidfd or something similar.

A lock file is adequate while the process is running, but still has race conditions in this use case. For example, if the program is killed after the other program tries to read the lock file. File locking is also unfortunately not an adequate primitive for IPC.

@ghost
Copy link
Author

ghost commented Jan 18, 2020

BTW, systemd is now using varlink for the homed API: https://systemd.io/USER_GROUP_API/

@emersion
Copy link
Owner

I agree with @cyclopsian. Adding a simple IPC mechanism doesn't add a lot of complexity.

@ghost
Copy link
Author

ghost commented Feb 5, 2020

This is updated, can squash/reorganize commits when everything is ready.

@@ -15,6 +15,7 @@ Dependencies:

* wayland-client
* scdoc (optional, for man pages)
* libvarlink
Copy link
Owner

Choose a reason for hiding this comment

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

Would be nice to explain that it's optional.

int kanshi_main_loop(struct kanshi_state *state);

#ifdef KANSHI_HAS_VARLINK
int kanshi_init_ipc(struct kanshi_state *state);
Copy link
Owner

Choose a reason for hiding this comment

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

Can we put these decls in a header file ipc.h?

#include <stdio.h>
#include <stdlib.h>

static int get_ipc_address(char *address, size_t size) {
Copy link
Owner

Choose a reason for hiding this comment

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

We don't put code in headers


static void signal_handler(int signum) {
if (write(signal_pipefds[1], &signum, sizeof(signum)) == -1) {
_exit(signum | 0x80);
Copy link
Owner

Choose a reason for hiding this comment

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

Maybe print an error message to stderr too?

struct kanshi_state *state = userdata;
kanshi_reload_config(state);
// ensure that changes are applied on the server before sending the response
struct wl_callback *callback = wl_display_sync(state->display);
Copy link
Owner

Choose a reason for hiding this comment

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

Ah, I see. This only ensures that the server has received the configuration request, the server is free to wait an arbitrary amount of time before applying the configuration.

We can add a TODO about using the wlr-output-management event instead.

char address[PATH_MAX];
get_ipc_address(address, sizeof(address));
if (varlink_service_new(&service,
"emersion", "kanshi", "1.1", "https://wayland.emersion.fr/kanshi/",
Copy link
Owner

Choose a reason for hiding this comment

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

Can we get this version number from a -D flag set by Meson?

Copy link
Owner

@emersion emersion left a comment

Choose a reason for hiding this comment

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

On the whole this looks pretty good to me! After these comments are addressed and the commits are re-organized I'll merge this.

Thanks for your work!

@somini
Copy link

somini commented Mar 25, 2020

What's the status of this?

This blocks https://github.com/cyclopsian/wdisplays/issues/4, from what I can tell.

@ghost
Copy link
Author

ghost commented Mar 25, 2020

Planning to finish this soon, due to current events I've been away from the main multi-monitor setup I have but I think I can find another way to test it.

@ghost
Copy link
Author

ghost commented May 17, 2020

Now that kanshi is in debian unstable, I'm trying to get libvarlink into debian before I finish this up https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=960434

@maricn
Copy link

maricn commented Mar 10, 2021

Just trying to get a sense if I should look into checking this branch out locally or if there's any chance @cyclopsian would be picking up the PR any time soon? And thanks for the work so far!

@maricn
Copy link

maricn commented Apr 13, 2021

Just trying to get a sense if I should look into checking this branch out locally or if there's any chance @cyclopsian would be picking up the PR any time soon? And thanks for the work so far!

OK, so this user has left GitHub, and is now replaced with the ghost account. 👻

I'm able to checkout this branch at varlink, but I don't code in C and it will take me another year to push this through. As the OP has left the GitHub, this is basically an open call for anyone to jump in, merge this with the mainline branch and address the rather minor PR comments, so - any takers?

@emersion
Copy link
Owner

Yes, anyone's welcome to jump it and adopt this work, keeping the attribution if applicable. I'd prefer to have two separate pull requests though (one for signal handling, another one for IPC).

@ericonr
Copy link
Contributor

ericonr commented Jun 30, 2021

Assuming no one's started work on this yet, I will try my hand on finishing up the PR.

@emersion
Copy link
Owner

Superseded by #107

@emersion emersion closed this Jul 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants