mirror of
https://github.com/lovell/sharp.git
synced 2025-07-13 12:20: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 {
|
struct ResizeBaton {
|
||||||
std::string fileIn;
|
std::string fileIn;
|
||||||
void* bufferIn;
|
char* bufferIn;
|
||||||
size_t bufferInLength;
|
size_t bufferInLength;
|
||||||
std::string iccProfilePath;
|
std::string iccProfilePath;
|
||||||
int limitInputPixels;
|
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 {
|
class ResizeWorker : public NanAsyncWorker {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -149,18 +163,25 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
|
|
||||||
// Input
|
// Input
|
||||||
ImageType inputImageType = ImageType::UNKNOWN;
|
ImageType inputImageType = ImageType::UNKNOWN;
|
||||||
VipsImage *image;
|
VipsImage *image = NULL;
|
||||||
if (baton->bufferInLength > 1) {
|
if (baton->bufferInLength > 1) {
|
||||||
// From buffer
|
// From buffer
|
||||||
inputImageType = DetermineImageType(baton->bufferIn, baton->bufferInLength);
|
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) {
|
if (inputImageType != ImageType::UNKNOWN) {
|
||||||
image = InitImage(inputImageType, baton->bufferIn, baton->bufferInLength, baton->accessMethod);
|
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");
|
(baton->err).append("Input buffer has corrupt header");
|
||||||
inputImageType = ImageType::UNKNOWN;
|
inputImageType = ImageType::UNKNOWN;
|
||||||
|
DeleteBuffer(NULL, buffer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(baton->err).append("Input buffer contains unsupported image format");
|
(baton->err).append("Input buffer contains unsupported image format");
|
||||||
|
DeleteBuffer(NULL, buffer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// From file
|
// From file
|
||||||
@ -175,7 +196,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
(baton->err).append("Input file is of an unsupported image format");
|
(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);
|
return Error(baton, hook);
|
||||||
}
|
}
|
||||||
vips_object_local(hook, image);
|
vips_object_local(hook, image);
|
||||||
@ -775,11 +796,6 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
void HandleOKCallback () {
|
void HandleOKCallback () {
|
||||||
NanScope();
|
NanScope();
|
||||||
|
|
||||||
// Free input Buffer
|
|
||||||
if (baton->bufferInLength > 0) {
|
|
||||||
g_free(baton->bufferIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Value> argv[3] = { NanNull(), NanNull(), NanNull() };
|
Handle<Value> argv[3] = { NanNull(), NanNull(), NanNull() };
|
||||||
if (!baton->err.empty()) {
|
if (!baton->err.empty()) {
|
||||||
// Error
|
// Error
|
||||||
@ -804,6 +820,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
if (baton->bufferOutLength > 0) {
|
if (baton->bufferOutLength > 0) {
|
||||||
// Copy data to new Buffer
|
// Copy data to new Buffer
|
||||||
argv[1] = NanNewBufferHandle(static_cast<char*>(baton->bufferOut), baton->bufferOutLength);
|
argv[1] = NanNewBufferHandle(static_cast<char*>(baton->bufferOut), baton->bufferOutLength);
|
||||||
|
// bufferOut was allocated via malloc
|
||||||
g_free(baton->bufferOut);
|
g_free(baton->bufferOut);
|
||||||
// Add buffer size to info
|
// Add buffer size to info
|
||||||
info->Set(NanNew<String>("size"), NanNew<Uint32>(static_cast<uint32_t>(baton->bufferOutLength)));
|
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();
|
Local<Object> buffer = options->Get(NanNew<String>("bufferIn"))->ToObject();
|
||||||
// Take a copy of the input Buffer to avoid problems with V8 heap compaction
|
// Take a copy of the input Buffer to avoid problems with V8 heap compaction
|
||||||
baton->bufferInLength = node::Buffer::Length(buffer);
|
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);
|
memcpy(baton->bufferIn, node::Buffer::Data(buffer), baton->bufferInLength);
|
||||||
options->Set(NanNew<String>("bufferIn"), NanNull());
|
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
|
// ICC profile to use when input CMYK image has no embedded profile
|
||||||
baton->iccProfilePath = *String::Utf8Value(options->Get(NanNew<String>("iccProfilePath"))->ToString());
|
baton->iccProfilePath = *String::Utf8Value(options->Get(NanNew<String>("iccProfilePath"))->ToString());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user