MCPcopy Index your code
hub / github.com/docker/cli / tryPluginRun

Function tryPluginRun

cmd/docker/docker.go:322–441  ·  view source on GitHub ↗
(ctx context.Context, dockerCli command.Cli, cmd *cobra.Command, subcommand string, envs []string)

Source from the content-addressed store, hash-verified

320}
321
322func tryPluginRun(ctx context.Context, dockerCli command.Cli, cmd *cobra.Command, subcommand string, envs []string) error {
323 plugincmd, err := pluginmanager.PluginRunCommand(dockerCli, subcommand, cmd)
324 if err != nil {
325 return err
326 }
327
328 // Establish the plugin socket, adding it to the environment under a
329 // well-known key if successful.
330 srv, err := socket.NewPluginServer(nil)
331 if err == nil {
332 plugincmd.Env = append(plugincmd.Env, socket.EnvKey+"="+srv.Addr().String())
333 defer func() {
334 // Close the server when plugin execution is over, so that in case
335 // it's still open, any sockets on the filesystem are cleaned up.
336 _ = srv.Close()
337 }()
338 }
339
340 // Set additional environment variables specified by the caller.
341 plugincmd.Env = append(plugincmd.Env, envs...)
342
343 // Background signal handling logic: block on the signals channel, and
344 // notify the plugin via the PluginServer (or signal) as appropriate.
345 const exitLimit = 2
346
347 // forceExitCh is closed by the signal goroutine just before it SIGKILLs
348 // the plugin. The main goroutine checks this after plugincmd.Run() returns
349 // and owns the final os.Exit(1) call, keeping exit-code ownership in one
350 // place and avoiding a race between two concurrent os.Exit calls.
351 forceExitCh := make(chan struct{})
352
353 tryTerminatePlugin := func(force bool) {
354 // If stdin is a TTY, the kernel will forward
355 // signals to the subprocess because the shared
356 // pgid makes the TTY a controlling terminal.
357 //
358 // The plugin should have its own copy of this
359 // termination logic, and exit after 3 retries
360 // on its own.
361 if dockerCli.Out().IsTerminal() {
362 return
363 }
364
365 // Terminate the plugin server, which closes
366 // all connections with plugin subprocesses,
367 // and signal them to exit.
368 //
369 // Repeated invocations result in EINVAL or EBADF,
370 // but that is fine for our purposes.
371 if srv != nil {
372 _ = srv.Close()
373 }
374
375 // force the process to terminate if it hasn't already
376 if force {
377 // Close forceExitCh before Kill so the channel is guaranteed
378 // to be closed by the time plugincmd.Run() returns: the plugin
379 // can only exit after Kill() delivers SIGKILL, and Run() only

Callers 1

runDockerFunction · 0.85

Calls 7

AddrMethod · 0.95
CloseMethod · 0.95
restoreTerminalFunction · 0.70
StringMethod · 0.65
OutMethod · 0.65
ErrMethod · 0.65
IsTerminalMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…