maildir,notmuch: avoid leaking open files
Previously, Message.NewReader returned the wrapped buffered reader without a reference to the opened file, so the files descriptors were left unclosed after reading. Now, the file reader is returned directly and closed on the call site. Buffering is not needed here because it is an implementation detail of go-message. Fixes: https://todo.sr.ht/~rjarry/aerc/9
This commit is contained in:
parent
beae17a6da
commit
904ffacb0e
|
@ -211,7 +211,7 @@ func parseAddressList(h *mail.Header, key string) ([]*mail.Address, error) {
|
||||||
|
|
||||||
// RawMessage is an interface that describes a raw message
|
// RawMessage is an interface that describes a raw message
|
||||||
type RawMessage interface {
|
type RawMessage interface {
|
||||||
NewReader() (io.Reader, error)
|
NewReader() (io.ReadCloser, error)
|
||||||
ModelFlags() ([]models.Flag, error)
|
ModelFlags() ([]models.Flag, error)
|
||||||
Labels() ([]string, error)
|
Labels() ([]string, error)
|
||||||
UID() uint32
|
UID() uint32
|
||||||
|
@ -225,6 +225,7 @@ func MessageInfo(raw RawMessage) (*models.MessageInfo, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
msg, err := message.Read(r)
|
msg, err := message.Read(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read message: %v", err)
|
return nil, fmt.Errorf("could not read message: %v", err)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -36,23 +36,17 @@ func TestMessageInfoHandledError(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockRawMessage struct {
|
type mockRawMessage struct {
|
||||||
body []byte
|
path string
|
||||||
}
|
|
||||||
|
|
||||||
func newMockRawMessage(body []byte) *mockRawMessage {
|
|
||||||
return &mockRawMessage{
|
|
||||||
body: body,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockRawMessageFromPath(p string) *mockRawMessage {
|
func newMockRawMessageFromPath(p string) *mockRawMessage {
|
||||||
b, err := ioutil.ReadFile(p)
|
return &mockRawMessage{
|
||||||
die(err)
|
path: p,
|
||||||
return newMockRawMessage(b)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockRawMessage) NewReader() (io.Reader, error) {
|
func (m *mockRawMessage) NewReader() (io.ReadCloser, error) {
|
||||||
return bytes.NewReader(m.body), nil
|
return os.Open(m.path)
|
||||||
}
|
}
|
||||||
func (m *mockRawMessage) ModelFlags() ([]models.Flag, error) { return nil, nil }
|
func (m *mockRawMessage) ModelFlags() ([]models.Flag, error) { return nil, nil }
|
||||||
func (m *mockRawMessage) Labels() ([]string, error) { return nil, nil }
|
func (m *mockRawMessage) Labels() ([]string, error) { return nil, nil }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package maildir
|
package maildir
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
@ -20,12 +19,8 @@ type Message struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReader reads a message into memory and returns an io.Reader for it.
|
// NewReader reads a message into memory and returns an io.Reader for it.
|
||||||
func (m Message) NewReader() (io.Reader, error) {
|
func (m Message) NewReader() (io.ReadCloser, error) {
|
||||||
f, err := m.dir.Open(m.key)
|
return m.dir.Open(m.key)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bufio.NewReader(f), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flags fetches the set of flags currently applied to the message.
|
// Flags fetches the set of flags currently applied to the message.
|
||||||
|
|
|
@ -159,6 +159,7 @@ func (w *Worker) searchKey(key uint32, criteria *searchCriteria,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
defer reader.Close()
|
||||||
bytes, err := ioutil.ReadAll(reader)
|
bytes, err := ioutil.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -432,6 +432,7 @@ func (w *Worker) handleFetchFullMessages(msg *types.FetchFullMessages) error {
|
||||||
w.worker.Logger.Printf("could not get message reader: %v", err)
|
w.worker.Logger.Printf("could not get message reader: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
w.worker.PostMessage(&types.FullMessage{
|
w.worker.PostMessage(&types.FullMessage{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
Content: &models.FullMessage{
|
Content: &models.FullMessage{
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package notmuch
|
package notmuch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -23,16 +22,12 @@ type Message struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReader returns a reader for a message
|
// NewReader returns a reader for a message
|
||||||
func (m *Message) NewReader() (io.Reader, error) {
|
func (m *Message) NewReader() (io.ReadCloser, error) {
|
||||||
name, err := m.Filename()
|
name, err := m.Filename()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
f, err := os.Open(name)
|
return os.Open(name)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bufio.NewReader(f), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageInfo populates a models.MessageInfo struct for the message.
|
// MessageInfo populates a models.MessageInfo struct for the message.
|
||||||
|
|
|
@ -367,6 +367,7 @@ func (w *worker) handleFetchFullMessages(msg *types.FetchFullMessages) error {
|
||||||
w.w.Logger.Printf("could not get message reader: %v", err)
|
w.w.Logger.Printf("could not get message reader: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
w.w.PostMessage(&types.FullMessage{
|
w.w.PostMessage(&types.FullMessage{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
Content: &models.FullMessage{
|
Content: &models.FullMessage{
|
||||||
|
|
Loading…
Reference in New Issue