forked from mirrors/gotosocial
[bugfix] Close ReadClosers properly in the media package (#434)
* defer lock reader * close readers when finished with them * close the reader in the teereader when finished
This commit is contained in:
parent
55ad6dee71
commit
73e9cca701
4 changed files with 52 additions and 18 deletions
|
@ -29,6 +29,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"codeberg.org/gruf/go-store/kv"
|
"codeberg.org/gruf/go-store/kv"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||||
|
@ -169,6 +170,15 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
|
||||||
return fmt.Errorf("store: error executing data function: %s", err)
|
return fmt.Errorf("store: error executing data function: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defer closing the reader when we're done with it
|
||||||
|
defer func() {
|
||||||
|
if rc, ok := reader.(io.ReadCloser); ok {
|
||||||
|
if err := rc.Close(); err != nil {
|
||||||
|
logrus.Errorf("store: error closing readcloser: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// extract no more than 261 bytes from the beginning of the file -- this is the header
|
// extract no more than 261 bytes from the beginning of the file -- this is the header
|
||||||
firstBytes := make([]byte, maxFileHeaderBytes)
|
firstBytes := make([]byte, maxFileHeaderBytes)
|
||||||
if _, err := reader.Read(firstBytes); err != nil {
|
if _, err := reader.Read(firstBytes); err != nil {
|
||||||
|
@ -205,13 +215,6 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
|
||||||
return fmt.Errorf("store: error storing stream: %s", err)
|
return fmt.Errorf("store: error storing stream: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the original reader is a readcloser, close it since we're done with it now
|
|
||||||
if rc, ok := reader.(io.ReadCloser); ok {
|
|
||||||
if err := rc.Close(); err != nil {
|
|
||||||
return fmt.Errorf("store: error closing readcloser: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.read = true
|
p.read = true
|
||||||
|
|
||||||
if p.postData != nil {
|
if p.postData != nil {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"codeberg.org/gruf/go-store/kv"
|
"codeberg.org/gruf/go-store/kv"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
terminator "github.com/superseriousbusiness/exif-terminator"
|
terminator "github.com/superseriousbusiness/exif-terminator"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
@ -260,6 +261,15 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
return fmt.Errorf("store: error executing data function: %s", err)
|
return fmt.Errorf("store: error executing data function: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defer closing the reader when we're done with it
|
||||||
|
defer func() {
|
||||||
|
if rc, ok := reader.(io.ReadCloser); ok {
|
||||||
|
if err := rc.Close(); err != nil {
|
||||||
|
logrus.Errorf("store: error closing readcloser: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// extract no more than 261 bytes from the beginning of the file -- this is the header
|
// extract no more than 261 bytes from the beginning of the file -- this is the header
|
||||||
firstBytes := make([]byte, maxFileHeaderBytes)
|
firstBytes := make([]byte, maxFileHeaderBytes)
|
||||||
if _, err := reader.Read(firstBytes); err != nil {
|
if _, err := reader.Read(firstBytes); err != nil {
|
||||||
|
@ -305,6 +315,15 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
return fmt.Errorf("store: couldn't process %s", extension)
|
return fmt.Errorf("store: couldn't process %s", extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// defer closing the clean reader when we're done with it
|
||||||
|
defer func() {
|
||||||
|
if rc, ok := clean.(io.ReadCloser); ok {
|
||||||
|
if err := rc.Close(); err != nil {
|
||||||
|
logrus.Errorf("store: error closing clean readcloser: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// now set some additional fields on the attachment since
|
// now set some additional fields on the attachment since
|
||||||
// we know more about what the underlying media actually is
|
// we know more about what the underlying media actually is
|
||||||
p.attachment.URL = uris.GenerateURIForAttachment(p.attachment.AccountID, string(TypeAttachment), string(SizeOriginal), p.attachment.ID, extension)
|
p.attachment.URL = uris.GenerateURIForAttachment(p.attachment.AccountID, string(TypeAttachment), string(SizeOriginal), p.attachment.ID, extension)
|
||||||
|
@ -317,14 +336,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
return fmt.Errorf("store: error storing stream: %s", err)
|
return fmt.Errorf("store: error storing stream: %s", err)
|
||||||
}
|
}
|
||||||
p.attachment.Cached = true
|
p.attachment.Cached = true
|
||||||
|
|
||||||
// if the original reader is a readcloser, close it since we're done with it now
|
|
||||||
if rc, ok := reader.(io.ReadCloser); ok {
|
|
||||||
if err := rc.Close(); err != nil {
|
|
||||||
return fmt.Errorf("store: error closing readcloser: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.read = true
|
p.read = true
|
||||||
|
|
||||||
if p.postData != nil {
|
if p.postData != nil {
|
||||||
|
|
|
@ -180,9 +180,15 @@ func (p *processor) getAttachmentContent(ctx context.Context, requestingAccount
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything read from the readCloser by the media manager will be written into the bufferedWriter
|
// Make a TeeReader so that everything read from the readCloser by the media manager will be written into the bufferedWriter.
|
||||||
teeReader := io.TeeReader(readCloser, bufferedWriter)
|
// We wrap this in a teeReadCloser which implements io.ReadCloser, so that whoever uses the teeReader can close the readCloser
|
||||||
return teeReader, fileSize, nil
|
// when they're done with it.
|
||||||
|
trc := teeReadCloser{
|
||||||
|
teeReader: io.TeeReader(readCloser, bufferedWriter),
|
||||||
|
close: readCloser.Close,
|
||||||
|
}
|
||||||
|
|
||||||
|
return trc, fileSize, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the pipewriter after data has been piped into it, so the reader on the other side doesn't block;
|
// close the pipewriter after data has been piped into it, so the reader on the other side doesn't block;
|
||||||
|
|
|
@ -20,6 +20,7 @@ package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -61,3 +62,16 @@ func parseFocus(focus string) (focusx, focusy float32, err error) {
|
||||||
focusy = float32(fy)
|
focusy = float32(fy)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type teeReadCloser struct {
|
||||||
|
teeReader io.Reader
|
||||||
|
close func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t teeReadCloser) Read(p []byte) (n int, err error) {
|
||||||
|
return t.teeReader.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t teeReadCloser) Close() error {
|
||||||
|
return t.close()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue