Skip to content
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

Image Memory Leak #150

Closed
drwheeler opened this issue Feb 2, 2012 · 6 comments · Fixed by #1003
Closed

Image Memory Leak #150

drwheeler opened this issue Feb 2, 2012 · 6 comments · Fixed by #1003

Comments

@drwheeler
Copy link

This simple little loop chews through all the memory on my Debian box. I'm nulling the Image instance every time through.
Running with node --trace_gc tst6.js shows that garbage collection is happening but this script will use 2GB of memory in short order then get killed. In real life the interval would be 10s

...

setInterval(timestampImage, 100);

function timestampImage() {
var cameraImage = new Image;

cameraImage.onload = onLoad;
cameraImage.onerror = function(err) {
                          console.log(err);
                      };

cameraImage.src = blackJpeg;

cameraImage = null;

}

function onLoad() {

...

Put the image in a canvas, add a text timestamp, save

...

}

https://gist.github.com/1720778#file_timestamp.js

@tj
Copy link
Contributor

tj commented Feb 2, 2012

thanks for the report i'll take a peek tomorrow

@enobrev
Copy link

enobrev commented Feb 2, 2012

Having similar results, with the past couple versions, at least. Hadn't found the time to pull it out of my code to explicitly test it (nicely done, @drwheeler).

@tj
Copy link
Contributor

tj commented Feb 2, 2012

it's probably something pretty obvious, just need a minute to check it out, should have time today

@enobrev
Copy link

enobrev commented Feb 4, 2012

My C is incredibly subpar, so I'm not sure how to implement this correctly, but it seems to me that the data pointer is never freed when an image is successfully loaded. I assume that should happen in the destructor, but that's where my capability seems to fail miserably.

To test, in Image.cc, in the Image::loadJPEGFromBuffer method, I moved free(data); above the final if (status) condition and ran @drwheeler's test. The memory usage was stable.

Unfortunately, doing it there means there is no output, likely because according to the docs:

"The output buffer must be kept around until the cairo_surface_t is destroyed or cairo_surface_finish() is called on the surface."

I could go on about my silly attempts to initialize *data in the constructor and free it in the destructor, but I assume you get the idea. One of these days pointers may actually make some sense to me. Obviously not today.

@ghost
Copy link

ghost commented Mar 6, 2012

I also did a free(data) move as enobrev mentioned. In Image::loadJPEGFromBuffer in canvas/src/Image.cc

free(data);
if (status) {
    return status;
}

Followed by a node-waf configure build, that change seemed to resolve the leak for my specific usage of this library.

I saw the memory leak in XCode Instruments while looking at Malloc 's while attached to the node.js process (which is what lead me to the that loadJPEGFromBuffer).

I can't see what broke. I assume I'm doing something else wrong. It seemed to work for my simple case of doing a resize from buffer passed from redis before sending on to the browser through express. Not isolated at all, but code is here >> https://github.com/proksoup/thlip.com/blob/ffcb87ab723b2a98a74c2a9182075f6c2fc584b9/app.coffee#L265-L278

kesla added a commit to kesla/node-canvas that referenced this issue Apr 25, 2012
tj added a commit that referenced this issue Apr 25, 2012
Fixes Image memory leak (#150)
@tj tj closed this as completed Apr 25, 2012
@swogger
Copy link

swogger commented Dec 2, 2014

The issue is still there:
Calling this method several times completely fills the memory. (canvas version 1.1.6)

function loadImage(url, finish){
request.get({url:url, encoding:null}, imageLoaded);
function imageLoaded(err,res,body) {
if(err) return finish(err);
var image = new Image();
image.onerror = function(e) {
finish(e);
};
image.onload = function(){
finish(image);
};
image.src = new Buffer(body, 'binary');
};
}

zbjornson added a commit to zbjornson/node-canvas that referenced this issue Sep 16, 2017
Storing the onerror/onload callbacks in Persistent handles means they will never be GC'ed. If those functions have references to the image, then the image will never be GC'ed either.

Fixes Automattic#785
Fixes Automattic#150 (for real)
zbjornson added a commit to zbjornson/node-canvas that referenced this issue Sep 16, 2017
Storing the onerror/onload callbacks in Persistent handles means they will never be GC'ed. If those functions have references to the image, then the image will never be GC'ed either.

Fixes Automattic#785
Fixes Automattic#150 (for real)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants