Beispiel #1
0
// Signallistener returns a net.Listener that will be closed when standard OS
// stop signals are received.
func SignalListener(port int) (net.Listener, error) {
	addr := ":" + fmt.Sprint(port)
	l, err := net.Listen("tcp", addr)
	if err != nil {
		log.Errorln("govtil/net: Failed to listen on", port, err)
		return nil, err
	}

	// Close listen port on signals (causes http.Serve() to return)
	signal.Go(func(s os.Signal) {
		log.Debugf("govtil/net: Closing listen port %v due to signal %v", l.Addr().String(), s)
		l.Close()
	})

	return l, nil
}
Beispiel #2
0
// Split a ReadCloser into 'n' ReadClosers. When all returned ReadClosers have
// been Close()'d, then the underlying ReadCloser is also closed.
func SplitReadCloser(rc io.ReadCloser, n uint) []io.ReadCloser {
	var r []io.ReadCloser
	var w []io.WriteCloser
	cg := new(sync.WaitGroup)
	cg.Add(int(n))
	for i := 0; i < int(n); i++ {
		rp, wp := io.Pipe()
		brp := bufio.NewReader(rp)
		w = append(w, wp)
		rpx := &rproxy{
			i,
			rp,
			brp,
			cg,
		}
		r = append(r, rpx)
	}

	// Closer
	go func() {
		cg.Wait()
		rc.Close()
	}()

	// Read pump
	rpump := func() {
		var err error
		defer func() {
			if err != nil && err != io.EOF {
				log.Errorf("govtil/io/multiplex: rpump error: %v", err)
			}
			for i := 0; i < len(w); i++ {
				w[i].Close()
			}
		}()

		dec := gob.NewDecoder(rc)
		var chno uint
		var d []byte
		for {
			if err = dec.Decode(&chno); err != nil {
				return
			}
			if err = dec.Decode(&d); err != nil {
				return
			}
			if _, err = w[chno].Write(d); err != nil {
				if err == io.ErrClosedPipe {
					// closed sub-channel, keep serving other sub-channels
					log.Debugf("govtil/io/multiplex: sub-channel closed, dumping payload of len %v", len(d))
					continue
				} else {
					// something wrong, stop
					log.Debugf("govtil/io/multiplex: failed to write received payload of length %v to pipe for channel %v", len(d), chno)
					return
				}
			}
		}
	}

	go rpump()
	return r
}