mirror of
https://github.com/lovell/sharp.git
synced 2025-07-12 20:10:13 +02:00
Delete input buffer on postclose #151
Notify V8 GC of memory (de)allocation
This commit is contained in:
parent
8421e3aa5f
commit
855945bef2
@ -51,7 +51,7 @@ enum class Angle {
|
||||
|
||||
struct ResizeBaton {
|
||||
std::string fileIn;
|
||||
void* bufferIn;
|
||||
char* bufferIn;
|
||||
size_t bufferInLength;
|
||||
std::string iccProfilePath;
|
||||
int limitInputPixels;
|
||||
@ -125,6 +125,20 @@ struct ResizeBaton {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Delete input char[] buffer and notify V8 of memory deallocation
|
||||
Used as the callback function for the "postclose" signal
|
||||
*/
|
||||
static void DeleteBuffer(VipsObject *object, std::tuple<char*, size_t> *buffer) {
|
||||
char* data = std::get<0>(*buffer);
|
||||
size_t length = std::get<1>(*buffer);
|
||||
if (data != NULL) {
|
||||
delete[] data;
|
||||
}
|
||||
NanAdjustExternalMemory(static_cast<int>(-length));
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
class ResizeWorker : public NanAsyncWorker {
|
||||
|
||||
public:
|
||||
@ -149,18 +163,25 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
|
||||
// Input
|
||||
ImageType inputImageType = ImageType::UNKNOWN;
|
||||
VipsImage *image;
|
||||
VipsImage *image = NULL;
|
||||
if (baton->bufferInLength > 1) {
|
||||
// From buffer
|
||||
inputImageType = DetermineImageType(baton->bufferIn, baton->bufferInLength);
|
||||
std::tuple<char*, size_t> *buffer = new std::tuple<char*, size_t>(baton->bufferIn, baton->bufferInLength);
|
||||
if (inputImageType != ImageType::UNKNOWN) {
|
||||
image = InitImage(inputImageType, baton->bufferIn, baton->bufferInLength, baton->accessMethod);
|
||||
if (image == NULL) {
|
||||
if (image != NULL) {
|
||||
// Listen for "postclose" signal to delete input buffer
|
||||
g_signal_connect(image, "postclose", G_CALLBACK(DeleteBuffer), buffer);
|
||||
} else {
|
||||
// Could not read header data
|
||||
(baton->err).append("Input buffer has corrupt header");
|
||||
inputImageType = ImageType::UNKNOWN;
|
||||
DeleteBuffer(NULL, buffer);
|
||||
}
|
||||
} else {
|
||||
(baton->err).append("Input buffer contains unsupported image format");
|
||||
DeleteBuffer(NULL, buffer);
|
||||
}
|
||||
} else {
|
||||
// From file
|
||||
@ -175,7 +196,7 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
(baton->err).append("Input file is of an unsupported image format");
|
||||
}
|
||||
}
|
||||
if (inputImageType == ImageType::UNKNOWN) {
|
||||
if (image == NULL || inputImageType == ImageType::UNKNOWN) {
|
||||
return Error(baton, hook);
|
||||
}
|
||||
vips_object_local(hook, image);
|
||||
@ -775,11 +796,6 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
void HandleOKCallback () {
|
||||
NanScope();
|
||||
|
||||
// Free input Buffer
|
||||
if (baton->bufferInLength > 0) {
|
||||
g_free(baton->bufferIn);
|
||||
}
|
||||
|
||||
Handle<Value> argv[3] = { NanNull(), NanNull(), NanNull() };
|
||||
if (!baton->err.empty()) {
|
||||
// Error
|
||||
@ -804,6 +820,7 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
if (baton->bufferOutLength > 0) {
|
||||
// Copy data to new Buffer
|
||||
argv[1] = NanNewBufferHandle(static_cast<char*>(baton->bufferOut), baton->bufferOutLength);
|
||||
// bufferOut was allocated via malloc
|
||||
g_free(baton->bufferOut);
|
||||
// Add buffer size to info
|
||||
info->Set(NanNew<String>("size"), NanNew<Uint32>(static_cast<uint32_t>(baton->bufferOutLength)));
|
||||
@ -925,9 +942,11 @@ NAN_METHOD(resize) {
|
||||
Local<Object> buffer = options->Get(NanNew<String>("bufferIn"))->ToObject();
|
||||
// Take a copy of the input Buffer to avoid problems with V8 heap compaction
|
||||
baton->bufferInLength = node::Buffer::Length(buffer);
|
||||
baton->bufferIn = g_malloc(baton->bufferInLength);
|
||||
baton->bufferIn = new char[baton->bufferInLength];
|
||||
memcpy(baton->bufferIn, node::Buffer::Data(buffer), baton->bufferInLength);
|
||||
options->Set(NanNew<String>("bufferIn"), NanNull());
|
||||
// Notify V8 GC of memory allocation
|
||||
NanAdjustExternalMemory(static_cast<int>(baton->bufferInLength));
|
||||
}
|
||||
// ICC profile to use when input CMYK image has no embedded profile
|
||||
baton->iccProfilePath = *String::Utf8Value(options->Get(NanNew<String>("iccProfilePath"))->ToString());
|
||||
|
Loading…
x
Reference in New Issue
Block a user