bmatsuo / lmdb-go

Bindings for the LMDB C library
BSD 3-Clause "New" or "Revised" License
157 stars 59 forks source link

Should I call runtime.SetFinalizer(qe.env, qe.env.Close) in my NewQEnv? #74

Closed ghost closed 8 years ago

ghost commented 8 years ago

Execute me, @bmatsuo Below is my code:

type QEnvOpt struct {
    maxTopicNum  int
    topicMapSize int64
}

type QEnv struct {
    mu       sync.Mutex
    root     *string
    env      *lmdb.Env
    topicMap map[string]*QTopic
}

func NewQEnv(root *string, opt *QEnvOpt) (*QEnv, error) {
    env, err := lmdb.NewEnv()
    if err != nil {
        return nil, err
    }
    qe := new(QEnv)
    qe.root = root
    qe.env = env
    if opt != nil {
        qe.env.SetMapSize(opt.topicMapSize)
        qe.env.SetMaxDBs(opt.maxTopicNum)
    } else {
        qe.env.SetMapSize(DEFAULT_TOPIC_MAP_SIZE)
        qe.env.SetMaxDBs(DEFALUT_MAX_TOPOC_NUM)
    }
    err = qe.env.Open(*qe.root+ENV_META_NAME, lmdb.NoSync|lmdb.NoSubdir, 0644)
    if err != nil {
        qe.env.Close()
        return nil, err
    }
    dead, err := qe.env.ReaderCheck()
    if err != nil {
        return nil, err
    }
    log.Println("ReaderCheck clears: ", dead)
    runtime.SetFinalizer(qe.env, qe.env.Close)
    return qe, nil
}

I'm not sure if I need call

runtime.SetFinalizer(qe.env, qe.env.Close)

and when golang gc, will golang collect the pointers in a struct object?

type QEnv struct {
    mu       sync.Mutex
    root     *string
    env      *lmdb.Env
    topicMap map[string]*QTopic
}
bmatsuo commented 8 years ago

Setting a finalizer is not necessary. The NewEnv function sets a finalizer for every Env.

https://github.com/bmatsuo/lmdb-go/blob/master/lmdb/env.go#L76

However, you should attempt to make your calls to Env.Close explicit. The finalizers on types in the LMDB package are provided as a safety net to avoid leaking memory allocated in C. But, finalizers are not dependable for cleaning up resources quickly, and they are not guaranteed to always run before termination.

I would suggest you write a Close method for your QEnv type and call it when the QEnv is no longer in use.

ghost commented 8 years ago

@bmatsuo Get it! Thank you