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

Rework fork/exec strategy #8567

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kennylevinsen
Copy link
Member

@kennylevinsen kennylevinsen commented Feb 11, 2025

cmd_exec_process is used whenever sway is meant to execute a child process on behalf of the user, and had a lot of complexity.

In order to avoid having to wait on the user's process, a double-fork was used, which in turn required us to wait on the outer process. In order to track the child PID for launcher purposes, a pipe was used to transmit the PID back to sway.

This resulted in sway blocking for 5-6 ms per exec on my system, which is quite significant. The error handling was also quite lacking - the read loop did not handle errors at all for example.

Instead, teach sway to handle SIGCHLD and do away with the double-fork. This in turn allows us to get rid of the pipe as we can record the child's PID directly. This reduces the time we block to just 1.5 ms on my system. We'd be able to get down to just 150 µs if we could use posix_spawn(3), but posix_spawn(3) cannot reset NOFILE. clone(2) or vfork(2) would be alternatives, but that presents portability issues.

This change is replicated for swaybar, swaybg and swaynag handling, which had similar albeit less complicated implementations.

@emersion
Copy link
Member

Looks like a good idea!

Previously this was not possible due to Xwayland (wlroots was doing a waitpid()), but that has been addressed in wlroots.

cmd_exec_process is used whenever sway is meant to execute a child
process on behalf of the user, and had a lot of complexity.

In order to avoid having to wait on the user's process, a double-fork
was used, which in turn required us to wait on the outer process. In
order to track the child PID for launcher purposes, a pipe was used to
transmit the PID back to sway.

This resulted in sway blocking for 5-6 ms per exec on my system, which
is quite significant. The error handling was also quite lacking - the
read loop did not handle errors at all for example.

Instead, teach sway to handle SIGCHLD and do away with the double-fork.
This in turn allows us to get rid of the pipe as we can record the
child's PID directly. This reduces the time we block to just 1.5 ms on
my system. We'd be able to get down to just 150 µs if we could use
posix_spawn(3), but posix_spawn(3) cannot reset NOFILE. clone(2) or
vfork(2) would be alternatives, but that presents portability issues.

This change is replicated for swaybar, swaybg and swaynag handling,
which had similar albeit less complicated implementations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants