Skip to content

Commit c719dfb

Browse files
committed
plugins: run plugin with new process group ID
Changes were made in #4599 to provide a mechanism for the CLI to notify running plugin processes that they should exit, in order to improve the general CLI/plugin UX. The current implementation boils down to: 1. The CLI creates a socket 2. The CLI executes the plugin 3. The plugin connects to the socket 4. (When) the CLI receives a termination signal, it uses the socket to notify the plugin that it should exit 5. The plugin's gets notified via the socket, and cancels it's `cmd.Context`, which then gets handled appropriately This change works in most cases and fixes the issue it sets out to solve (see: docker/compose#11292) however, in the case where the user has a TTY attached and the plugin is not already handling received signals, steps 4+ changes: 4. (When) the CLI receives a termination signal, before it can use the socket to notify the plugin that it should exit, the plugin process also receives a signal due to sharing the pgid with the CLI Since we now have a proper "job control" mechanism, we can simplify the scenarios by executing the plugins with their own process group id, thereby removing the "double notification" issue and making it so that plugins can handle the same whether attached to a TTY or not. In order to make this change "plugin-binary" backwards-compatible, in the case that a plugin does not connect to the socket, the CLI passes the signal to the plugin process. Signed-off-by: Laura Brehm <[email protected]>
1 parent 7d92573 commit c719dfb

4 files changed

Lines changed: 20 additions & 1 deletion

File tree

cli-plugins/manager/manager.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
232232
cmd.Stdin = os.Stdin
233233
cmd.Stdout = os.Stdout
234234
cmd.Stderr = os.Stderr
235+
configureOSSpecificCommand(cmd)
235236

236237
cmd.Env = os.Environ()
237238
cmd.Env = append(cmd.Env, ReexecEnvvar+"="+os.Args[0])

cli-plugins/manager/manager_unix.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@
22

33
package manager
44

5+
import (
6+
"os/exec"
7+
"syscall"
8+
)
9+
510
var defaultSystemPluginDirs = []string{
611
"/usr/local/lib/docker/cli-plugins", "/usr/local/libexec/docker/cli-plugins",
712
"/usr/lib/docker/cli-plugins", "/usr/libexec/docker/cli-plugins",
813
}
14+
15+
func configureOSSpecificCommand(cmd *exec.Cmd) {
16+
cmd.SysProcAttr = &syscall.SysProcAttr{
17+
Setpgid: true,
18+
}
19+
}

cli-plugins/manager/manager_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ package manager
22

33
import (
44
"os"
5+
"os/exec"
56
"path/filepath"
67
)
78

89
var defaultSystemPluginDirs = []string{
910
filepath.Join(os.Getenv("ProgramData"), "Docker", "cli-plugins"),
1011
filepath.Join(os.Getenv("ProgramFiles"), "Docker", "cli-plugins"),
1112
}
13+
14+
func configureOSSpecificCommand(cmd *exec.Cmd) {
15+
// no-op
16+
}

cmd/docker/docker.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,14 @@ func tryPluginRun(dockerCli command.Cli, cmd *cobra.Command, subcommand string,
230230
// we send a SIGKILL to the plugin process and exit
231231
go func() {
232232
retries := 0
233-
for range signals {
233+
for s := range signals {
234234
if conn != nil {
235235
if err := conn.Close(); err != nil {
236236
_, _ = fmt.Fprintf(dockerCli.Err(), "failed to signal plugin to close: %v\n", err)
237237
}
238238
conn = nil
239+
} else {
240+
plugincmd.Process.Signal(s)
239241
}
240242
retries++
241243
if retries >= exitLimit {

0 commit comments

Comments
 (0)