globalsign / mgo

The MongoDB driver for Go
Other
1.97k stars 231 forks source link

Panic on mgo.Session.Ping when session closed #354

Open baloo32 opened 5 years ago

baloo32 commented 5 years ago

We use the Ping method to check periodically if the service is available, and if not, to try and auto-connect in case it is a temporary connection issue.

I am encountering an issue on closing a running server where a call to an in-progress Ping fails with a panic: Session already closed rather than an expected error return.


What version of MongoDB are you using (mongod --version)?

db version v3.6.11
git version: b4339db12bf57ffee5b84a95c6919dbd35fe31c9
OpenSSL version: OpenSSL 1.0.2o-fips  27 Mar 2018
allocator: tcmalloc
modules: none
build environment:
    distmod: 2008plus-ssl
    distarch: x86_64
    target_arch: x86_64

What version of Go are you using (go version)?

go version go1.11.9 windows/amd64

What operating system and processor architecture are you using (go env)?

set GOARCH=amd64
set GOBIN=D:\Development\Go\bin
set GOCACHE=C:\Users\XXXXX\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\Development\work\go
set GOPROXY=
set GORACE=
set GOROOT=D:\Development\Go
set GOTMPDIR=
set GOTOOLDIR=D:\Development\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\XXXXX\AppData\Local\Temp\go-build398815790=/tmp/go-build -gno-record-gcc-switches

What did you do?

// Create the session and Dial Mongo
    var mgoSession *mgo.Session
    configDBOnce.Do(func() {
        // Dial Mongo - get session
        mgoSession, err = mgo.Dial(dbHost)
        if err != nil {
            return
        }
        // Check session is alive
        err = mgoSession.Ping()
        if err != nil {
            return
        }
        // Make sure session alive by pinging MongoDB every second and refreshing session if needed
        KeepAlive(dbName, mgoSession)

        ConfigDB = &MongoDB{mgoSession.DB(dbName)}
    })

// KeepAlive pings MongoDB every interval and refreshes session if needed
func KeepAlive(dbName string, mgoSession *mgo.Session) {
    go func() {
        for {
            time.Sleep(time.Second * 5)
            if err := mgoSession.Ping(); err != nil {
                log.Print(fmt.Sprintf("Lost Mongo connection to %s: %s. Restoring...", dbName, err))
                mgoSession.Refresh()
            }
        }
    }()
}

When sending a terminate to the server, the following panic is thrown rather than the err being returned from .Ping() to be handled gracefully.

panic: Session already closed

goroutine 70 [running]:
github.com/globalsign/mgo.(*Session).cluster(...)
        D:/Development/work/go/src/github.com/globalsign/mgo/session.go:2071
github.com/globalsign/mgo.(*Session).acquireSocket(0xc00029e1a0, 0xc000344001, 0x0, 0x0, 0x0)
        D:/Development/work/go/src/github.com/globalsign/mgo/session.go:5141 +0x9b7
github.com/globalsign/mgo.(*Database).Run(0xc000563e98, 0x11f7f20, 0x1536ca0, 0x0, 0x0, 0x0, 0x0)
        D:/Development/work/go/src/github.com/globalsign/mgo/session.go:992 +0x67
github.com/globalsign/mgo.(*Session).Run(0xc00029e1a0, 0x11f7f20, 0x1536ca0, 0x0, 0x0, 0xc0002ea200, 0xc000318780)
        D:/Development/work/go/src/github.com/globalsign/mgo/session.go:2489 +0xa5
github.com/globalsign/mgo.(*Session).Ping(0xc00029e1a0, 0x0, 0x0)
        D:/Development/work/go/src/github.com/globalsign/mgo/session.go:2525 +0x64
github.com/tripism/api/db.KeepAlive.func1(0xc00029e1a0, 0xc000078468, 0xb)
        D:/Development/work/go/src/github.com/tripism/api/db/db.go:119 +0x6b
created by github.com/tripism/api/db.KeepAlive
        D:/Development/work/go/src/github.com/tripism/api/db/db.go:116 +0x68
exit status 2