beam: more hooks for interactive debugging
This inserts low-level hooks for interactive step-by-step debugging. Hooks are triggered by setting the *TEST* environment variable. This is particularly useful for tracking down file descriptor leaks, double-closing, or other issues which are difficult to debug with the usual toolbox. Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
This commit is contained in:
parent
a14c83eca3
commit
3b5c1c4203
1 changed files with 24 additions and 3 deletions
27
beam/unix.go
27
beam/unix.go
|
@ -9,7 +9,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func debugCheckpoint(msg string, args ...interface{}) {
|
func debugCheckpoint(msg string, args ...interface{}) {
|
||||||
return
|
if os.Getenv("DEBUG") == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
os.Stdout.Sync()
|
os.Stdout.Sync()
|
||||||
tty,_ := os.OpenFile("/dev/tty", os.O_RDWR, 0700)
|
tty,_ := os.OpenFile("/dev/tty", os.O_RDWR, 0700)
|
||||||
fmt.Fprintf(tty, msg, args...)
|
fmt.Fprintf(tty, msg, args...)
|
||||||
|
@ -103,6 +105,7 @@ func Receive(conn *net.UnixConn) (rdata []byte, rf *os.File, rerr error) {
|
||||||
// without complicating application code.
|
// without complicating application code.
|
||||||
//
|
//
|
||||||
func SendPipe(conn *net.UnixConn, data []byte) (endpoint *net.UnixConn, err error) {
|
func SendPipe(conn *net.UnixConn, data []byte) (endpoint *net.UnixConn, err error) {
|
||||||
|
debugCheckpoint("===DEBUG=== SendPipe('%s'). Hit enter to confirm: ", data)
|
||||||
local, remote, err := SocketPair()
|
local, remote, err := SocketPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -167,7 +170,20 @@ func socketpair() ([2]int, error) {
|
||||||
// not bound to the underlying filesystem.
|
// not bound to the underlying filesystem.
|
||||||
// Messages sent on one end are received on the other, and vice-versa.
|
// Messages sent on one end are received on the other, and vice-versa.
|
||||||
// It is the caller's responsibility to close both ends.
|
// It is the caller's responsibility to close both ends.
|
||||||
func SocketPair() (*os.File, *os.File, error) {
|
func SocketPair() (a *os.File, b *os.File, err error) {
|
||||||
|
defer func() {
|
||||||
|
var (
|
||||||
|
fdA int = -1
|
||||||
|
fdB int = -1
|
||||||
|
)
|
||||||
|
if a != nil {
|
||||||
|
fdA = int(a.Fd())
|
||||||
|
}
|
||||||
|
if b != nil {
|
||||||
|
fdB = int(b.Fd())
|
||||||
|
}
|
||||||
|
debugCheckpoint("===DEBUG=== SocketPair() = [%d-%d]. Hit enter to confirm: ", fdA, fdB)
|
||||||
|
}()
|
||||||
pair, err := socketpair()
|
pair, err := socketpair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -176,6 +192,8 @@ func SocketPair() (*os.File, *os.File, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func USocketPair() (*net.UnixConn, *net.UnixConn, error) {
|
func USocketPair() (*net.UnixConn, *net.UnixConn, error) {
|
||||||
|
debugCheckpoint("===DEBUG=== USocketPair(). Hit enter to confirm: ")
|
||||||
|
defer debugCheckpoint ("===DEBUG=== USocketPair() returned. Hit enter to confirm ")
|
||||||
a, b, err := SocketPair()
|
a, b, err := SocketPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -199,7 +217,10 @@ func USocketPair() (*net.UnixConn, *net.UnixConn, error) {
|
||||||
// returns an error if the file descriptor does not point to a unix socket.
|
// returns an error if the file descriptor does not point to a unix socket.
|
||||||
// This creates a duplicate file descriptor. It's the caller's responsibility
|
// This creates a duplicate file descriptor. It's the caller's responsibility
|
||||||
// to close both.
|
// to close both.
|
||||||
func FdConn(fd int) (*net.UnixConn, error) {
|
func FdConn(fd int) (n*net.UnixConn, err error) {
|
||||||
|
{
|
||||||
|
debugCheckpoint("===DEBUG=== FdConn([%d]) = (unknown fd). Hit enter to confirm: ", fd)
|
||||||
|
}
|
||||||
f := os.NewFile(uintptr(fd), fmt.Sprintf("%d", fd))
|
f := os.NewFile(uintptr(fd), fmt.Sprintf("%d", fd))
|
||||||
conn, err := net.FileConn(f)
|
conn, err := net.FileConn(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue