Skip to content

Netflix/go-iomux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

iomux

Go Reference

iomux allows multiplexing of file descriptors using any Go supported unix domain network. It makes it possible to distinctly capture exec.Cmd stdout/stderr keeping the original output order:

	mux := &iomux.Mux[OutputType]{}
	defer mux.Close()
	cmd := exec.Command("sh", "-c", "echo out1 && echo err1 1>&2 && echo out2")
	stdout, _ := mux.Tag(StdOut) // errors ignored for brevity
	stderr, _ := mux.Tag(StdErr)
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	taggedData, _ := mux.ReadWhile(func() error {
		return cmd.Run()
	})
	for _, td := range taggedData {
		var w io.Writer
		switch td.Tag {
		case StdOut:
			w = os.Stdout
		case StdErr:
			w = os.Stderr
		}
		binary.Write(w, binary.BigEndian, td.Data)
	}

When using unixgram networking, ordering is guaranteed (see Limitations below). More can be found in the examples directory.

This module was inspired by Josh Triplett's Rust crate https://github.com/joshtriplett/io-mux/.

Limitations

On all platforms except macOS the network defaults to unixgram. On Linux, unixgram behaves like a pipe and will behave exactly as you'd expect, and always see messages in order. On other UNIXes, there is a possibility of different behaviour when buffers are full, but it's unlikely a reader will be outpaced.

Using unixgram on macOS when you cannot control the write size of the sender, is impossible due a message size limit of 2048 bytes:

write /dev/stdout: message too long

So on macOs, the default network is unix. It is connection oriented, so it doesn't come with the ordering guarantees of unixgram. It's possible to see see writes out of order, but on a MacBook Pro M1 0.1ms is the threshold for writes being read out of order, so for real world use cases it's unlikely to be a problem.

These limitations do not affect the read order of an individual connection, so output for an individual tag is always consistent. If you prefer a different network type, the default can be overridden using the convenience constructors NewMuxUnix, NewMuxUnixGram and NewMuxUnixPacket.