nodejs native c++ npm module memory error, cairo image processing

Я прослушивал TJ на node-canvasоб ускорении кода, над которым я работаю в форке модуля узла, который он создал и поддерживает.

Я обнаружил, что Canvas.toBuffer() убивает ресурсы нашего конвейера, и создал альтернативу, которая просто преобразует Canvas в изображение, не проходя через буфер png / URL-адрес носителя. Проблема в том, что cairo — это таинственный зверь, и существует дополнительный уровень беспокойства по поводу памяти, выделенной в модулях узлов, чтобы не получить GC'd от матери v8. Я добавил соответствующие HandleScopes ко всем необходимым функциям, которые получают доступ к данным V8.

Я смог протестировать метод Canvas.loadImage(image) тысячи раз в моей установке Mac (6.18), а также автономные тесты на наших серверах ubuntu / production, работающих под управлением той же версии узла. Но когда код запускается как фоновый процесс/сервер и координируется Gearman, я получаю некоторые «интересные» модули памяти/segfaults.

Кроме того, у меня возникают проблемы с вызовом любого из методов классов, определенных в node-canvas, которые не встроены в заголовочные файлы. В качестве побочного вопроса Как лучше всего создавать общие пакеты исходного кода, на которые могут положиться другие модули узлов?

Я попытался воссоздать проблему и запустить ее с помощью gdb, node_g и всех модулей узлов, построенных с помощью символов и отладочных флагов. Но ошибка возникает в lib за пределами источника, для которого я могу получить трассировку стека.

Для справки вот где я вызываю loadImageData, и хотя он работает локально в различных условиях, в нашей производственной среде, когда он тщательно спрятан в фрейм-сервере, он, по-видимому, вызывает segfaults (вчера провел день, пытаясь gdb node_g наш серверный код, но фрейм-серверы запускаются gearman... TL;DR не получил трассировку стека основных причин)

https://github.com/victusfate/node-canvas/blob/master/src/Canvas.cc#L497

Handle
 Canvas::LoadImage(const Arguments &args) {
   HandleScope scope;
   LogStream mout(LOG_DEBUG,"node-canvas.paint.ccode.Canvas.LoadImage");    
   mout << "Canvas::LoadImage top " << LogStream::endl;

   Canvas *canvas = ObjectWrap::Unwrap(args.This());
   if (args.Length() < 1) {
     mout << "Canvas::LoadImage Error requires one argument of Image type " << LogStream::endl;
     return ThrowException(Exception::TypeError(String::New("Canvas::LoadImage requires one argument of Image type")));
   }

   Local obj = args[0]->ToObject();
   Image *img = ObjectWrap::Unwrap(obj);
   canvas->loadImageData(img);
   return Undefined();
}  

void Canvas::loadImageData(Image *img) {
  LogStream mout(LOG_DEBUG,"node-canvas.paint.ccode.Canvas.loadImageData");    
  if (this->isPDF()) {
    mout << "Canvas::loadImageData pdf canvas type " << LogStream::endl;
    cairo_surface_finish(this->surface());
    closure_t *closure = (closure_t *) this->closure();

    int w = cairo_image_surface_get_width(this->surface());
    int h = cairo_image_surface_get_height(this->surface());

    img->loadFromDataBuffer(closure->data,w,h);
    mout << "Canvas::loadImageData pdf type, finished loading image" << LogStream::endl;
  }
  else {
    mout << "Canvas::loadImageData data canvas type " << LogStream::endl;
    cairo_surface_flush(this->surface());
    int w = cairo_image_surface_get_width(this->surface());
    int h = cairo_image_surface_get_height(this->surface());

    img->loadFromDataBuffer(cairo_image_surface_get_data(this->surface()),w,h);
    mout << "Canvas::loadImageData image type, finished loading image" << LogStream::endl;
  }   
}

и вот как выглядит текущий метод в Image (я удалил некоторые закомментированные сведения о журнале) https://github.com/victusfate/node-canvas/blob/master/src/Image.cc#L240

/*
 * load from data buffer width*height*4 bytes
 */
cairo_status_t
Image::loadFromDataBuffer(uint8_t *buf, int width, int height) {
  this->clearData();
  int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width); // 4*width + ?
  this->_surface = cairo_image_surface_create_for_data(buf,CAIRO_FORMAT_ARGB32,width,height,stride);
  this->data_mode = DATA_IMAGE;
  this->loaded();
  cairo_status_t status = cairo_surface_status(_surface);
  if (status) return status;
  return CAIRO_STATUS_SUCCESS;
}

Мы будем признательны за любую помощь, профессиональные советы, содействие или слова ободрения.

Родом из групп Google

15
задан Mark Essel 11 June 2012 в 13:11
поделиться