Path: blob/main/components/supervisor/pkg/activation/activation.go
2500 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package activation56import (7"context"8"net"9"os"10"sync"1112"github.com/gitpod-io/gitpod/common-go/log"13"github.com/moredure/easygo/netpoll"14"golang.org/x/xerrors"15)1617// Callback is called when a listener is written to. Receivers are expected to close socketFD.18type Callback func(socketFD *os.File) error1920// Listen polls on the listener and calls callback when someone writes to it.21func Listen(ctx context.Context, l net.Listener, activate Callback) error {22poller, err := netpoll.New(&netpoll.Config{23OnWaitError: func(err error) {24log.WithError(err).Error("netpoll: wait loop error")25},26})27if err != nil {28return err29}30defer poller.Close()3132// Get netpoll descriptor with EventRead|EventEdgeTriggered.33desc, err := netpoll.HandleListener(l, netpoll.EventRead|netpoll.EventEdgeTriggered)34if err != nil {35return err36}37defer desc.Close()3839var (40runc = make(chan bool, 1)41once sync.Once42)4344err = poller.Start(desc, func(ev netpoll.Event) {45defer once.Do(func() {46_ = poller.Stop(desc)4748close(runc)49})5051if ev&netpoll.EventReadHup != 0 {52return53}5455runc <- true56})57if err != nil {58return err59}6061select {62case run := <-runc:63if !run {64return nil65}66case <-ctx.Done():67return ctx.Err()68}6970var f *os.File71switch ll := l.(type) {72case *net.UnixListener:73f, err = ll.File()74case *net.TCPListener:75f, err = ll.File()76default:77return xerrors.Errorf("unsuported listener")78}79if err != nil {80return err81}82return activate(f)83}848586