Skip to content

Background wl-copy inherits caller's process group and is suspended by terminal job control #298

Open

Description

@ryjen

Problem

wl-copy backgrounds itself after acquiring the clipboard selection, but the clipboard-serving child remains in the caller's process group.

If wl-copy is launched by a foreground terminal application and that application is suspended with Ctrl-Z, the terminal sends SIGTSTP to the foreground process group. This also stops the background wl-copy process.

The clipboard selection still points to that stopped provider, so subsequent paste requests can block indefinitely.

Minimal reproduction

sh -c 'printf test | wl-copy; sleep 9999'

Press Ctrl-Z, then run:

wl-paste

The paste blocks.

The process state can be inspected with:

ps -o pid,ppid,pgid,sid,stat,tty,cmd -C wl-copy
jobs -l

The background wl-copy provider remains in the same PGID as the suspended foreground job and has a stopped (T) state.

Sending SIGCONT to the wl-copy process allows the pending paste to complete again.

Cause

The current background path redirects stdin/stdout, changes directory, ignores SIGHUP, and then forks:

pid_t pid = fork();

if (pid < 0) {
    perror("fork");
}

if (pid > 0) {
    exit(0);
}

The forked child inherits the parent's process group, so although it is described as running "in the background", it remains part of the original terminal job for job-control purposes.

Possible fix

Would it make sense for the clipboard-serving child to enter a separate process group when --foreground is not used?

For example, the parent could put the child into its own process group before exiting:

if (pid > 0) {
    if (setpgid(pid, pid) < 0) {
        perror("setpgid");
    }
    exit(0);
}

Doing this from the parent avoids a race where the original wl-copy process could exit before the child changes its own process group.

This would keep the clipboard provider in the same session while preventing terminal job-control signals directed at the caller's foreground process group from stopping it.

Using setsid() also avoids the problem, but creating a new process group seems like the smaller behavioral change.

Originally observed in

I first encountered this through OpenCode on Wayland:

anomalyco/opencode#42162

Running wl-copy through setsid fixes the OpenCode reproduction.

Related issues

These discuss why wl-copy remains alive after copying, but do not appear to cover the inherited process-group / SIGTSTP behavior:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions