Fixed reporting leaks for GLCtrl in Linux with Radeon driver, new memory leaks detection related functions.

This commit is contained in:
Mirek Fidler 2021-12-19 14:53:30 +01:00
parent 38b6807ff4
commit d8d16229d1
9 changed files with 110 additions and 10 deletions

View file

@ -440,10 +440,15 @@ void Exit(int code)
throw ExitExc();
}
void MemorySetMainBegin__();
void MemorySetMainEnd__();
void AppExecute__(void (*app)())
{
try {
MemorySetMainBegin__();
(*app)();
MemorySetMainEnd__();
}
catch(ExitExc) {
return;

View file

@ -170,6 +170,11 @@ inline void TinyFree(int, void *ptr) { return MemoryFree(ptr); }
#endif
dword MemoryGetCurrentSerial();
void MemoryIgnoreNonMainLeaks();
void MemoryIgnoreNonUppThreadsLeaks();
struct MemoryIgnoreLeaksBlock {
MemoryIgnoreLeaksBlock() { MemoryIgnoreLeaksBegin(); }
~MemoryIgnoreLeaksBlock() { MemoryIgnoreLeaksEnd(); }

View file

@ -69,6 +69,8 @@ struct sThreadParam {
bool noshutdown;
};
static thread_local bool sUppThread = false;
static
#ifdef PLATFORM_WIN32
#ifdef CPU_64
@ -82,6 +84,7 @@ static
sThreadRoutine(void *arg)
{
LLOG("sThreadRoutine");
sUppThread = true;
auto p = (sThreadParam *)arg;
try {
p->cb();
@ -191,6 +194,11 @@ Thread::~Thread()
#endif
}
bool Thread::IsUpp()
{
return sUppThread;
}
bool Thread::IsST() //the containing thread (of wich there may be multiple) has not run its Run() yet
{
return !threadr;

View file

@ -80,6 +80,7 @@ public:
static bool IsST();
static bool IsMain();
static bool IsUpp();
static int GetCount();
static void BeginShutdownThreads();
static void EndShutdownThreads();

View file

@ -2,6 +2,39 @@
// #define LOGAF
namespace Upp {
static bool sIgnoreNonMainLeaks;
static bool sIgnoreNonUppThreadsLeaks;
static dword serial_number = 0;
static dword serial_main_begin;
static dword serial_main_end;
dword MemoryGetCurrentSerial() { return serial_number; }
void MemoryIgnoreNonMainLeaks()
{ // ignore leaks outside _APP_MAIN
sIgnoreNonMainLeaks = true;
}
void MemoryIgnoreNonUppThreadsLeaks()
{ // ignore leaks in threads not launched by U++ Thread
sIgnoreNonUppThreadsLeaks = true;
}
void MemorySetMainBegin__()
{
serial_main_begin = serial_number;
}
void MemorySetMainEnd__()
{
serial_main_end = serial_number;
}
};
#if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP)
int sMemDiagInitCount;
@ -85,12 +118,14 @@ void *MemoryAllocSz_(size_t& size);
void DbgSet(DbgBlkHeader *p, size_t size)
{
static dword serial_number = 0;
bool allow_leak = s_ignoreleaks ||
sIgnoreNonUppThreadsLeaks && !Thread::IsUpp() && !Thread::IsMain()
#if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP)
p->serial = sMemDiagInitCount == 0 || s_ignoreleaks ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
#else
p->serial = s_ignoreleaks ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
|| sMemDiagInitCount == 0
#endif
;
p->serial = allow_leak ? 0 : ~ ++serial_number ^ (dword)(uintptr_t) p;
p->size = size;
if(s_allocbreakpoint && s_allocbreakpoint == serial_number)
__BREAK__;
@ -209,7 +244,8 @@ void MemoryDumpLeaks()
bool leaks = false;
int n = 0;
while(p != &dbg_live) {
if(p->serial) {
dword serial = (unsigned int)~(p->serial ^ (uintptr_t)p);
if(p->serial && (!sIgnoreNonMainLeaks || serial >= serial_main_begin && serial < serial_main_end)) {
if(!leaks)
VppLog() << "\n\nHeap leaks detected:\n";
leaks = true;
@ -222,7 +258,6 @@ void MemoryDumpLeaks()
++n;
p = p->next;
}
sprintf(b, "%d", n);
VppLog() << "\n*** TOO MANY LEAKS (" << n << ") TO LIST THEM ALL\n";
break;
}

View file

@ -63,7 +63,7 @@ is slightly faster.&]
[s2;%% Attempts to change the size of block at [%-*@3 ptr] to something
closer to [%-*@3 newsize]. The real value is returned in [%-*@3 newsize].
Returns true on success.&]
[s3;%% &]
[s3; &]
[s4; &]
[s5;:Upp`:`:TinyAlloc`(int`): [@(0.0.255) void]_`*[* TinyAlloc]([@(0.0.255) int]_[*@3 size])&]
[s2;%% Allocates the block of [%-*@3 size] bytes. This allows for allocation
@ -76,7 +76,7 @@ TinyFree.&]
e], [@(0.0.255) void]_`*[*@3 ptr])&]
[s2;%% Frees the block allocated with TinyAlloc, [%-*@3 size] has to
be the same as during allocation.&]
[s3;%% &]
[s3; &]
[s4; &]
[s5;:Upp`:`:tiny`_new`(Args`.`.`.args`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T],
[@(0.0.255) class...]_[*@4 Args]>_[*@4 T]_`*[* tiny`_new]([*@4 Args][@(0.0.255) ...]_args)&]
@ -122,6 +122,43 @@ b])&]
[s2;%% This debug / diagnostics function limits memory usage to [%-*@3 kb]
KBs. If the application allocates more, it stops with error.&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:MemoryGetCurrentSerial`(`): [_^Upp`:`:dword^ dword]_[* MemoryGetCurrentSerial
]()&]
[s2;%% In debug mode, returns the serial number of the next allocated
block. This number is eventually listed in the log in case there
are any leaks.&]
[s3; &]
[s4; &]
[s5;:Upp`:`:MemoryIgnoreNonMainLeaks`(`): [@(0.0.255) void]_[* MemoryIgnoreNonMainLeaks](
)&]
[s2;%% Makes leaks detector ignore leaks by global constructors.&]
[s3; &]
[s4; &]
[s5;:Upp`:`:MemoryIgnoreNonUppThreadsLeaks`(`): [@(0.0.255) void]_[* MemoryIgnoreNonUppTh
readsLeaks]()&]
[s2;%% Makes leaks dectector ignore leaks created by threads that
are not launched by U`+`+ Thread class.&]
[s3; &]
[s4; &]
[s5;:Upp`:`:MemoryIgnoreLeaksBegin`(`): [@(0.0.255) void]_[* MemoryIgnoreLeaksBegin]()&]
[s2;%% Makes leak detector ignore leaks of blocks allocated until
[%-* MemoryIgnoreLeaksEnd ]is called. Calls can be nested. This
is especially useful when working with 3rd party code that might
e.g. create static leaks (memory is allocated just once, but
library does not bother to deallocate on exit).&]
[s3; &]
[s4; &]
[s5;:Upp`:`:MemoryIgnoreLeaksEnd`(`): [@(0.0.255) void]_[* MemoryIgnoreLeaksEnd]()&]
[s2;%% Ends the suppression started by MemoryIgnoreLeaksBegin.&]
[s3;%% &]
[s4; &]
[s1;:Upp`:`:MemoryIgnoreLeaksBlock`:`:struct: [@(0.0.255) struct]_[* MemoryIgnoreLeaksBlo
ck]&]
[s2;%% This helper class calls [%-* MemoryIgnoreLeaksBegin] in constructor
and [%-* MemoryIgnoreLeaksEnd], in other works supresses leaks
till the end of block.&]
[s3;%% &]
[ {{10000F(128)G(128)@1 [s0;%% [* Heap tuning]]}}&]
[s0;%% &]
[s0;%% Heap tuning is provided through MemoryOptions class. Constructor

View file

@ -91,14 +91,19 @@ t]_[*@3 ms])&]
[s3;%- &]
[s4;%- &]
[s5;:Thread`:`:IsST`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsST]()&]
[s2; No additional thread was started yet (only the main thread is
running so far).&]
[s2; No additional U`+`+ Thread was started yet (only the main thread
is running so far).&]
[s3;%- &]
[s4;%- &]
[s5;:Thread`:`:IsMain`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsMain]()&]
[s2; Returns true if current thread is main.&]
[s3;%- &]
[s4;%- &]
[s5;:Upp`:`:Thread`:`:IsUpp`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsUpp]()&]
[s2; Calling thread was started using U`+`+ Thread class (for main
thread returns false).&]
[s3;%- &]
[s4;%- &]
[s5;:Thread`:`:GetCount`(`):%- [@(0.0.255) static] [@(0.0.255) int]_[* GetCount]()&]
[s2; Number of running threads (started using Thread class).&]
[s3;%- &]

View file

@ -32,6 +32,8 @@ void GLCtrl::Init()
Add(pane.SizePos());
#endif
restore_gl_viewport__ = SetCurrentViewport;
MemoryIgnoreNonMainLeaks();
MemoryIgnoreNonUppThreadsLeaks(); // Linux drivers leak memory in threads
}
Image GLCtrl::MouseEvent(int event, Point p, int zdelta, dword keyflags)

View file

@ -90,6 +90,8 @@ void GLCtrl::Create()
void GLCtrl::Sync()
{
MemoryIgnoreLeaksBlock __;
if(win) {
Rect r = GetScreenView() - GetTopCtrl()->GetScreenRect().TopLeft();
bool b = IsVisible() && r.GetWidth() > 0 && r.GetHeight() > 0;