New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mime/multipart: TempFile file hangs around on disk after usage in multipart/formdata.go #20253

Open
nilslice opened this Issue May 5, 2017 · 10 comments

Comments

Projects
None yet
10 participants
@nilslice

nilslice commented May 5, 2017

Hey Go team,

I'd like to know if this is a bug or expected behavior. If it is a bug, I would like to write a patch to fix it.


Please answer these questions before submitting your issue. Thanks!

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

go version go1.8 linux/amd64

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

GOOS="linux"
GOARCH="amd64"

What did you do?

When uploading a file to a Go HTTP server, the call to req.ParseMultipartForm() subsequently calls readForm() and if the file size exceeds the maxMemory setting it creates a file on disk using the ioutil.TempFile() func, but the resulting file is never removed by the Go program. Unix behavior aside, based on the documentation for ioutil.TempFile(), the caller should remove the file once it is done using it. The file is only ever removed from the Go program if the io.Copy returns a non-nil error.

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.

I would need to show a lot of code to demonstrate this, but you can see in the Go src here how the file is never removed: https://github.com/golang/go/blob/master/src/mime/multipart/formdata.go#L78

A link on play.golang.org is best.

What did you expect to see?

I expect that the temp file is removed after the file is copied to it's designated location on disk.

What did you see instead?

my /tmp directory is littered with multipart-XXXXXXXX files

@bradfitz

This comment has been minimized.

Show comment
Hide comment
@bradfitz

bradfitz May 5, 2017

Member

When you're done with the multipart files, you can call:
https://golang.org/pkg/mime/multipart/#Form.RemoveAll

... which is accessible here:
https://golang.org/pkg/net/http/#Request.MultipartForm

But, yeah, maybe this could be more automatic. Maybe the multipart.File's concrete type could delete-on-Close.

Feel free to work on it!

Member

bradfitz commented May 5, 2017

When you're done with the multipart files, you can call:
https://golang.org/pkg/mime/multipart/#Form.RemoveAll

... which is accessible here:
https://golang.org/pkg/net/http/#Request.MultipartForm

But, yeah, maybe this could be more automatic. Maybe the multipart.File's concrete type could delete-on-Close.

Feel free to work on it!

@bradfitz bradfitz changed the title from ioutil.TempFile file hangs around on disk after usage in multipart/formdata.go to mime/multipart: TempFile file hangs around on disk after usage in multipart/formdata.go May 5, 2017

@bradfitz bradfitz added this to the Go1.10 milestone May 5, 2017

@nilslice

This comment has been minimized.

Show comment
Hide comment
@nilslice

nilslice May 5, 2017

Thanks for the suggestions! I wasn't aware of Form.RemoveAll - good to know.

From my perspective, the complete process of dealing with HTML forms / other HTTP clients uploading files to my server shouldn't involve removing the temp files w/ RemoveAll. Based on the UX of a typical Go programmer, automatically cleaning up those files doesn't feel overly magical to me.

I'll work on it and submit if something clicks.

nilslice commented May 5, 2017

Thanks for the suggestions! I wasn't aware of Form.RemoveAll - good to know.

From my perspective, the complete process of dealing with HTML forms / other HTTP clients uploading files to my server shouldn't involve removing the temp files w/ RemoveAll. Based on the UX of a typical Go programmer, automatically cleaning up those files doesn't feel overly magical to me.

I'll work on it and submit if something clicks.

@kennygrant

This comment has been minimized.

Show comment
Hide comment
@kennygrant

kennygrant Nov 3, 2017

Contributor

@nilslice still working on this?

We were hit by a similar problem (have small servers accepting file uploads, and tmp files filled the disk at times if not flushed regularly), and I too was unaware of Form.RemoveAll, but delete on close would be even better.

Happy to look at it if you're busy or leave it to you if you'd like to look at it.

Contributor

kennygrant commented Nov 3, 2017

@nilslice still working on this?

We were hit by a similar problem (have small servers accepting file uploads, and tmp files filled the disk at times if not flushed regularly), and I too was unaware of Form.RemoveAll, but delete on close would be even better.

Happy to look at it if you're busy or leave it to you if you'd like to look at it.

@nilslice

This comment has been minimized.

Show comment
Hide comment
@nilslice

nilslice Nov 3, 2017

@kennygrant - I have a partial fix, but have been swamped with other work. If it's imperative to your project that it's patched, go for it! Otherwise, I'd still like to finish it. But no problem whatsoever if you want to get the patch in.

nilslice commented Nov 3, 2017

@kennygrant - I have a partial fix, but have been swamped with other work. If it's imperative to your project that it's patched, go for it! Otherwise, I'd still like to finish it. But no problem whatsoever if you want to get the patch in.

@kennygrant

This comment has been minimized.

Show comment
Hide comment
@kennygrant

kennygrant Nov 3, 2017

Contributor

That's ok, I'll leave it to you if you have started. We have a workaround for now.

Contributor

kennygrant commented Nov 3, 2017

That's ok, I'll leave it to you if you have started. We have a workaround for now.

@rsc rsc modified the milestones: Go1.10, Go1.11 Nov 22, 2017

@Kagami

This comment has been minimized.

Show comment
Hide comment

Kagami commented Mar 17, 2018

@nilslice

This comment has been minimized.

Show comment
Hide comment
@nilslice

nilslice Mar 17, 2018

@Kagami - it does appear to make the call, but the last time I tested it the files were still on disk.

The blame shows that the code has been in the tree for ~7 years, well before this issue was originally filed: https://github.com/golang/go/blame/678dede7bc22a7cccfe78c42711478a9b1ecf4d3/src/net/http/server.go#L1553-L1555

Have you tried this to verify that the files are cleaned up after the request?

I'm trying to get my CL out this month or early next (taking a couple days off from work to do long put-off open source tasks I have queued up!).

nilslice commented Mar 17, 2018

@Kagami - it does appear to make the call, but the last time I tested it the files were still on disk.

The blame shows that the code has been in the tree for ~7 years, well before this issue was originally filed: https://github.com/golang/go/blame/678dede7bc22a7cccfe78c42711478a9b1ecf4d3/src/net/http/server.go#L1553-L1555

Have you tried this to verify that the files are cleaned up after the request?

I'm trying to get my CL out this month or early next (taking a couple days off from work to do long put-off open source tasks I have queued up!).

@andybons andybons added the NeedsFix label Mar 19, 2018

petergtz added a commit to petergtz/go that referenced this issue May 14, 2018

mime/multipart: properly remove temp files in case of error
The new implementation properly uses the err variable defined in the
return values, instead of declaring a new local-scoped err variable.

Updates golang#20253
@gopherbot

This comment has been minimized.

Show comment
Hide comment
@gopherbot

gopherbot May 14, 2018

Change https://golang.org/cl/113055 mentions this issue: mime/multipart: properly remove temp files in case of error

gopherbot commented May 14, 2018

Change https://golang.org/cl/113055 mentions this issue: mime/multipart: properly remove temp files in case of error

@lpar

This comment has been minimized.

Show comment
Hide comment
@lpar

lpar Aug 14, 2018

If this won't be fully fixed in 1.10, how about mentioning the need to call RemoveAll in the documentation for ParseMultipartForm?

lpar commented Aug 14, 2018

If this won't be fully fixed in 1.10, how about mentioning the need to call RemoveAll in the documentation for ParseMultipartForm?

@dvdscripter

This comment has been minimized.

Show comment
Hide comment
@dvdscripter

dvdscripter Aug 21, 2018

I'm no expert but you should be able to remove files without closing them?

...
file, _, err := r.FormFile("file")
if err != nil {
	return err
}
defer file.Close()
...

Leaves no "multipart*" files behind.

dvdscripter commented Aug 21, 2018

I'm no expert but you should be able to remove files without closing them?

...
file, _, err := r.FormFile("file")
if err != nil {
	return err
}
defer file.Close()
...

Leaves no "multipart*" files behind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment