go 迭代channel

54 阅读1分钟

runc源码中:

// forward handles the main signal event loop forwarding, resizing, or reaping depending
// on the signal received.
func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach bool) (int, error) {
	

	// Handle and forward signals.
	for s := range h.signals {  / 这里会一直阻塞吗?
		switch s {
		case unix.SIGWINCH:
                        // ...
		case unix.SIGCHLD:
			// ...
		case unix.SIGURG:
			// SIGURG is used by go runtime for async preemptive
			// scheduling, so runc receives it from time to time,
			// and it should not be forwarded to the container.
			// Do nothing.
		default:
			us := s.(unix.Signal)
			logrus.Debugf("forwarding signal %d (%s) to %d", int(us), unix.SignalName(us), pid1)
			if err := unix.Kill(pid1, us); err != nil {
				logrus.Error(err)
			}
		}
	}
	return -1, nil
}

答案是:是的, 会一直阻塞。 系统会把所有Signal全部转发给Runc.

这里给出一个简单的示例证明一下:对channel执行迭代操作会阻塞。

package main

import (
	"fmt"
	"golang.org/x/sys/unix"
	"os"
	"os/signal"
)

func main() {

	s := make(chan os.Signal, 1)
	signal.Notify(s)

	for c := range s {  // 会一直循环
		switch c {
		default:
			us := c.(unix.Signal)
			fmt.Println(us.String())
		}
	}
}

一个更加简单的例子:

package main

import (
	"fmt"
	"time"
)

func main() {

	s := make(chan bool, 1)
	go func() {
		for{
			s<- false
			time.Sleep(5*time.Second)
		}

	}()
	for c := range s { // 会一直阻塞
		switch c {
		default:
			fmt.Println(c)
		}
	}
}