Repaint class cleanup, found memory leak

Stacktrace refactored
presentation
Andreas Butti 7 years ago
parent c895b7e97a
commit a64580ad5d
  1. 1
      CMakeLists.txt
  2. 5
      src/Xournalpp.cpp
  3. 106
      src/control/jobs/RenderJob.cpp
  4. 115
      src/control/jobs/RepaintWidgetHandler.cpp
  5. 45
      src/control/jobs/RepaintWidgetHandler.h
  6. 58
      src/util/Stacktrace.cpp
  7. 8
      src/util/Stacktrace.h
  8. 1
      src/util/XournalTypeList.h

@ -181,6 +181,7 @@ if (BUILD_POPPLER)
# Comment out, seems to be a problem on Debian...
# Do we need to detect something to enable / disable?
# -lopenjpeg
-lbacktrace
${JPEG_LIBRARIES}
${PopplerLibs_LDFLAGS}
${lcms_LDFLAGS}

@ -19,11 +19,6 @@ int main(int argc, char* argv[])
{
// init crash handler
installCrashHandlers();
if (argc)
{
// Filename is needed to get backtracke with filenumbers
Stacktrace::setExename(argv[0]);
}
#ifdef DEV_CALL_LOG
Log::initlog();

@ -1,4 +1,5 @@
#include "RenderJob.h"
#include "RepaintWidgetHandler.h"
#include "gui/PageView.h"
#include "gui/XournalView.h"
@ -118,111 +119,6 @@ void RenderJob::rerenderRectangle(Rectangle* rect, bool noThreads)
rerenderRectangle(this, rect, noThreads);
}
class RepaintWidgetHandler
{
public:
RepaintWidgetHandler(GtkWidget * width)
{
g_mutex_init(&this->mutex);
this->widget = width;
this->complete = false;
this->rescaleId = 0;
}
public:
void repaintComplete()
{
g_mutex_lock(&this->mutex);
this->complete = true;
for (Rectangle* r : this->rects)
{
delete r;
r = NULL;
}
this->rects.clear();
addRepaintCallback();
g_mutex_unlock(&this->mutex);
}
void repaintRects(Rectangle* rect)
{
g_mutex_lock(&this->mutex);
if (this->complete)
{
delete rect;
rect = NULL;
}
else
{
this->rects.push_front(rect);
}
addRepaintCallback();
g_mutex_unlock(&this->mutex);
}
private:
static bool idleRepaint(RepaintWidgetHandler * data)
{
g_mutex_lock(&data->mutex);
bool complete = data->complete;
std::list<Rectangle*> rects = data->rects;
data->rects.clear();
data->complete = false;
data->rescaleId = 0;
g_mutex_unlock(&data->mutex);
gdk_threads_enter();
gtk_widget_queue_draw(data->widget);
if (complete)
{
//gtk_widget_queue_draw(data->widget);
}
else
{
for (Rectangle* r : rects)
{
delete r;
r = NULL;
}
rects.clear();
}
gdk_flush();
gdk_threads_leave();
// do not call again
return false;
}
void addRepaintCallback()
{
if (this->rescaleId)
{
return;
}
this->rescaleId = g_idle_add((GSourceFunc) idleRepaint, this);
}
private:
GMutex mutex;
int rescaleId;
bool complete;
std::list<Rectangle*> rects;
GtkWidget* widget;
};
RepaintWidgetHandler* handler = NULL;
void RenderJob::run(bool noThreads)

@ -0,0 +1,115 @@
#include "RepaintWidgetHandler.h"
RepaintWidgetHandler::RepaintWidgetHandler(GtkWidget * width)
{
XOJ_INIT_TYPE(RepaintWidgetHandler);
g_mutex_init(&this->mutex);
this->widget = width;
this->complete = false;
this->rescaleId = 0;
}
RepaintWidgetHandler::~RepaintWidgetHandler()
{
XOJ_CHECK_TYPE(RepaintWidgetHandler);
for (Rectangle* r : this->rects)
{
delete r;
}
this->rects.clear();
XOJ_RELEASE_TYPE(RepaintWidgetHandler);
}
void RepaintWidgetHandler::repaintComplete()
{
XOJ_CHECK_TYPE(RepaintWidgetHandler);
g_mutex_lock(&this->mutex);
this->complete = true;
for (Rectangle* r : this->rects)
{
delete r;
}
this->rects.clear();
addRepaintCallback();
g_mutex_unlock(&this->mutex);
}
void RepaintWidgetHandler::repaintRects(Rectangle* rect)
{
XOJ_CHECK_TYPE(RepaintWidgetHandler);
g_mutex_lock(&this->mutex);
if (this->complete)
{
delete rect;
rect = NULL;
}
else
{
this->rects.push_front(rect);
}
addRepaintCallback();
g_mutex_unlock(&this->mutex);
}
bool RepaintWidgetHandler::idleRepaint(RepaintWidgetHandler * data)
{
XOJ_CHECK_TYPE_OBJ(data, RepaintWidgetHandler);
g_mutex_lock(&data->mutex);
bool complete = data->complete;
std::list<Rectangle*> rects = data->rects;
data->rects.clear();
data->complete = false;
data->rescaleId = 0;
g_mutex_unlock(&data->mutex);
gdk_threads_enter();
gtk_widget_queue_draw(data->widget);
if (complete)
{
//gtk_widget_queue_draw(data->widget);
}
else
{
for (Rectangle* r : rects)
{
delete r;
r = NULL;
}
rects.clear();
}
gdk_flush();
gdk_threads_leave();
// do not call again
return false;
}
void RepaintWidgetHandler::addRepaintCallback()
{
XOJ_CHECK_TYPE(RepaintWidgetHandler);
if (this->rescaleId)
{
return;
}
this->rescaleId = g_idle_add((GSourceFunc) idleRepaint, this);
}

@ -0,0 +1,45 @@
/*
* Xournal++
*
* Repaint helper class
*
* @author Xournal++ Team
* https://github.com/xournalpp/xournalpp
*
* @license GNU GPLv2 or later
*/
#pragma once
#include <XournalType.h>
#include <Rectangle.h>
#include <gtk/gtk.h>
#include <list>
class RepaintWidgetHandler
{
public:
RepaintWidgetHandler(GtkWidget * width);
~RepaintWidgetHandler();
public:
void repaintComplete();
void repaintRects(Rectangle* rect);
private:
static bool idleRepaint(RepaintWidgetHandler * data);
void addRepaintCallback();
private:
XOJ_TYPE_ATTRIB;
GMutex mutex;
int rescaleId;
bool complete;
std::list<Rectangle*> rects;
GtkWidget* widget;
};

@ -1,50 +1,52 @@
#include "Stacktrace.h"
#include <execinfo.h>
#include <iostream>
using std::endl;
/**
* This code uses addr2line
*
* Another solution would be backtrace-symbols.c from cairo/util, but its really complicated
*/
#include <string.h>
#include <backtrace.h>
#include <cxxabi.h>
string exeName = "";
using std::endl;
Stacktrace::Stacktrace() { }
Stacktrace::~Stacktrace() { }
void Stacktrace::setExename(string name)
void Stacktrace::printStracktrace(std::ostream& stream)
{
exeName = name;
stream << "Backtrace: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
struct backtrace_state* lbstate = backtrace_create_state(nullptr, 1, (backtrace_error_callback)errorCallback, &stream);
backtrace_full(lbstate, 0, (backtrace_full_callback)fullCallback, (backtrace_error_callback)errorCallback, &stream);
stream << "Backtrace end <<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl;
}
void Stacktrace::printStracktrace(std::ostream& stream)
int Stacktrace::fullCallback(std::ostream* stream, uintptr_t pc, const char* filename, int lineno, const char* function)
{
void* trace[32];
char** messages = (char**) NULL;
char buff[2048];
int trace_size = backtrace(trace, 32);
messages = backtrace_symbols(trace, trace_size);
int demangle_status = 0;
char *realname = abi::__cxa_demangle(function, 0, 0, &demangle_status);
// skip first stack frame (points here)
for (int i = 1; i < trace_size; ++i)
if (demangle_status != 0 && function != NULL)
{
stream << "[bt] #" << i << " " << messages[i] << endl;
realname = ::strdup(function);
}
char syscom[1024];
*stream << "0x" << std::hex << (unsigned long) pc << "\t";
*stream << (realname == nullptr ? "???" : realname) << "\t";
*stream << (filename == nullptr ? "???" : filename) << ":";
*stream << std::dec << lineno << endl;
sprintf(syscom, "addr2line %p -e %s", trace[i], exeName.c_str());
FILE* fProc = popen(syscom, "r");
while (fgets(buff, sizeof(buff), fProc) != NULL)
{
stream << buff;
}
pclose(fProc);
free(realname);
if (function == NULL)
{
return 0;
}
return strcmp(function, "main") == 0 ? 1 : 0;
}
void Stacktrace::errorCallback(std::ostream* stream, const char* msg, int errnum)
{
*stream << "Something went wrong in libbacktrace: " << msg << endl;
}
void Stacktrace::printStracktrace()

@ -11,8 +11,6 @@
#pragma once
#include "StringUtils.h"
#include <iostream>
class Stacktrace
@ -22,8 +20,10 @@ private:
virtual ~Stacktrace();
public:
static void setExename(string name);
static void printStracktrace();
static void printStracktrace(std::ostream& stream);
private:
static void errorCallback(std::ostream* stream, const char* msg, int errnum);
static int fullCallback(std::ostream* stream, uintptr_t pc, const char* filename, int lineno, const char* function);
};

@ -226,5 +226,6 @@ XOJ_DECLARE_TYPE(ImageElementView, 215);
XOJ_DECLARE_TYPE(PdfElementView, 216);
XOJ_DECLARE_TYPE(MainWindowToolbarMenu, 216);
XOJ_DECLARE_TYPE(LastSelectedTool, 217);
XOJ_DECLARE_TYPE(RepaintWidgetHandler, 218);
//XOJ_DECLARE_TYPE(XXXXXXXXXXXXXXXX, 206);

Loading…
Cancel
Save