c970948d477fdf14f826f763cb171984ccc2a302 — Hugo Osvaldo Barrera 2 months ago df860d0
Block until targets are reached

And expand docs on how to make sure the locker is ready before the
target is reached.
2 files changed, 24 insertions(+), 9 deletions(-)

M main.go
M README.md => README.md +14 -8
@@ 57,17 57,24 @@ The service itself must be enabled for the current user:
Additionally, service files must be created and enabled for any service that
should start when the system is locked.

For example, `enabling` this service file would run `slock`:
For example, `enabling` this service file would run `swaylock` when `logind`
locks the session and before the system goes to sleep:

    Description=A simple X screen locker
    Description=Screen locker for Wayland
    # If swaylock exits cleanly, unlock the session:
    # When lock.target is stopped, stops this too:
    # Delay lock.target until this service is ready:

    # Unlock the session when the screen locker exit:
    ExecStopPost=/usr/bin/loginctl unlock-session
    # systemd will consider this service started when swaylock forks...
    # ... and swaylock will fork only after it has locked the screen.
    ExecStart=/usr/bin/swaylock -f


@@ 115,8 122,7 @@ Changelog

- Sleeping will be now inhibited when `systemd-lock-handler` starts. This
  ensure that there is enough time to react before the system actually goes to
  sleep. See [this article] for some background on how this all works and
  upcoming changes.
  sleep. See [this article] for some background on how this.

[this article]: https://whynothugo.nl/journal/2022/10/26/systemd-locking-and-sleeping/

M main.go => main.go +10 -1
@@ 13,18 13,27 @@ import (

// Starts a systemd unit and blocks until the job is completed.
func StartSystemdUserUnit(unitName string) error {
	conn, err := systemd.NewUserConnectionContext(context.Background())
	if err != nil {
		return fmt.Errorf("failed to connect to systemd user session: %v", err)

	ch := make(chan string, 1)

	_, err = conn.StartUnitContext(context.Background(), unitName, "replace", nil)
	if err != nil {
		return fmt.Errorf("failed to start unit: %v", err)

	log.Println("Started systemd unit:", unitName)
	result := <-ch
	if result == "done" {
		log.Println("Started systemd unit:", unitName)
	} else {
		return fmt.Errorf("failed to start unit %v: %v", unitName, result)

	return nil