Skip to content

internal/kawa: stop Run when its context is canceled - #24

Merged
DeedleFake merged 3 commits into
masterfrom
kawa-cancel
Oct 2, 2026
Merged

DeedleFake merged 3 commits into
masterfrom
kawa-cancel

Conversation

@DeedleFake

Copy link
Copy Markdown
Owner

Why

Server.Run took a context but ignored it, and cmd/kawa had no signal handling, so SIGTERM killed kawa outright with status 143. Run now returns nil when its context is canceled, and cmd/kawa cancels that context on SIGINT or SIGTERM.

wl_display_terminate is not safe to call from another goroutine. It sets a plain bool, and wl_display_run resets that bool when it starts, so an early call is lost. Instead, a context.AfterFunc writes a byte to a pipe that the event loop watches with EventLoop.AddFd. The loop reads the byte and terminates the display itself. A cancel that comes before the loop starts waits in the pipe until it does.

Scope

  • loopPipe in internal/kawa/pipe.go holds the pipe and event source that exited used to set up inline. exited and the new canceled pipe both use it. newLoopPipe also closes the pipe if a later setup step fails, and checks that AddFd succeeded.
  • Before release closes the pipe, Run stops the AfterFunc, or waits for its write if it has already started. That happens on every return, Log Out included.
  • Run calls runtime.LockOSThread. wlroots keeps per-thread state between calls. A GLES2 render pass makes its EGL context current in begin and releases it in submit, and the GL calls between them are separate cgo calls. Today every render pass runs inside a frame callback, which already pins the goroutine, so nothing visible changes. The lock keeps the setup calls before the loop on the loop's thread too.
  • cmd/kawa uses signal.NotifyContext for os.Interrupt and syscall.SIGTERM. After the first signal it calls the returned stop, so a second signal still kills kawa if shutdown hangs.
  • Run still does not destroy Xwayland or the display after the loop exits, so the X lock, the X socket, and the Wayland socket stay behind as before.

Blast Radius

SIGINT and SIGTERM now go through the normal return from Run, so kawa exits with status 0 instead of dying from the signal. Log Out behaves as before. The exited pipe behind New moved into loopPipe and keeps its behavior.

Verification

  • go vet, go test, golangci-lint run --disable=errcheck, and go fix -diff are clean, and each commit builds. A -race build stopped with SIGTERM reports no races.
  • kawa ran nested on a private Xvfb with foot and xlogo connected. SIGTERM, SIGINT, and Log Out each exited with status 0 in 0.1 s to 0.3 s. The log after the stop has the same single Xwayland failed to read Wayland events: Broken pipe line as master. Master exits with 143 on SIGTERM.
  • SIGTERM sent from 6 ms to 400 ms after start, while init runs and before the loop starts, still exits with 0. Sent within 3 ms, before main installs its handler, it kills kawa with 143.
  • verify-kawa covered boot, the registry, New with weston-terminal, the New box that clears when its program exits without a window, xlogo through Xwayland, and Log Out.

wl_display_terminate is not safe to call from another goroutine, so a
context.AfterFunc writes to a pipe that the event loop watches, and the
loop terminates the display itself. Run returns nil in that case.

Run also locks its goroutine to one OS thread. wlroots keeps per-thread
state between calls, such as the EGL context that a GLES2 render pass
holds current from begin to submit.
The first SIGINT or SIGTERM cancels the context given to Run. A second
one gets the default behavior, so it still kills kawa if shutting down
gets stuck.
@DeedleFake
DeedleFake added this pull request to stack #26 October 2, 2026 21:56
@DeedleFake DeedleFake changed the title kawa: stop Run when its context is canceled internal/kawa: stop Run when its context is canceled Oct 2, 2026
@DeedleFake
DeedleFake merged commit 88d7e85 into master Oct 2, 2026
1 check passed
@DeedleFake
DeedleFake deleted the kawa-cancel branch October 2, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant