Re: How to debug FinalizeError?

2018-11-29 Thread unDEFER via Digitalmars-d-learn
On Thursday, 29 November 2018 at 14:51:40 UTC, Steven 
Schveighoffer wrote:
You need to compile druntime in debug mode. One thing you can 
do is implement the function locally, and then break on it 
(it's a C linkage, so I think the linker will grab your copy 
instead of the one in druntime)


i.e. in your code, do:

extern(C) void onFinalizeError(TypeInfo info, Throwable e, 
string file = __FILE__, size_t line = __LINE__)

{
   import core.stdc.stdio;
   printf("break here\n");
}


Big thanks, Steve. I will try it. Every night will do debugging 
and maybe at one night it will happen again :-)


Re: How to debug FinalizeError?

2018-11-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 11/29/18 2:07 AM, unDEFER wrote:
No I'm not preallocating any exceptions. It was idea, but I removed all 
calls which can make throw.
I'm using very old dmd 2.074.1, so as I have patched it for my text 
editor with IDE functions. I had a year break in development, so now I 
need to rewrite all my patches.

But exactly the output of my program looks like this:

core.exception.FinalizeError@src/rt/lifetime.d(1407): Finalization error

=== Bypassed ===

 BerkeleyDB exceptions mixed with output of destructors 
||


core.exception.InvalidMemoryOperationError@src/core/exception.d(696): 
Invalid memory operation



It means that "Invalid memory operation" occurred earlier than 
"Finalization error"?

The line on which shows the pointer src/rt/lifetime.d(1407) is exactly:
     onFinalizeError(*pc, e);
Why gdb doesn't see this function?


You need to compile druntime in debug mode. One thing you can do is 
implement the function locally, and then break on it (it's a C linkage, 
so I think the linker will grab your copy instead of the one in druntime)


i.e. in your code, do:

extern(C) void onFinalizeError(TypeInfo info, Throwable e, string file = 
__FILE__, size_t line = __LINE__)

{
   import core.stdc.stdio;
   printf("break here\n");
}



My program (the text editor) had run test all night under gdb with break 
on InvalidMemoryOperationError and didn't fall. So it is very-very-very 
hard to reproduce.
And I haven't ideas where maybe this throw. At least I don't see any 
throw in explicit form.


These are unfortunately really tough to debug. You get very little info, 
and the stack trace is generally useless.


-Steve


Re: How to debug FinalizeError?

2018-11-28 Thread unDEFER via Digitalmars-d-learn
No I'm not preallocating any exceptions. It was idea, but I 
removed all calls which can make throw.
I'm using very old dmd 2.074.1, so as I have patched it for my 
text editor with IDE functions. I had a year break in 
development, so now I need to rewrite all my patches.

But exactly the output of my program looks like this:

core.exception.FinalizeError@src/rt/lifetime.d(1407): 
Finalization error


=== Bypassed ===

 BerkeleyDB exceptions mixed with output of 
destructors ||


core.exception.InvalidMemoryOperationError@src/core/exception.d(696): Invalid 
memory operation


It means that "Invalid memory operation" occurred earlier than 
"Finalization error"?
The line on which shows the pointer src/rt/lifetime.d(1407) is 
exactly:

onFinalizeError(*pc, e);
Why gdb doesn't see this function?

My program (the text editor) had run test all night under gdb 
with break on InvalidMemoryOperationError and didn't fall. So it 
is very-very-very hard to reproduce.
And I haven't ideas where maybe this throw. At least I don't see 
any throw in explicit form.


Re: How to debug FinalizeError?

2018-11-28 Thread Adam D. Ruppe via Digitalmars-d-learn

On Wednesday, 28 November 2018 at 22:40:17 UTC, unDEFER wrote:
Hello! After long-long time of debugging, I just have decided 
InvalidMemoryOperationError in my program. But now my program 
after few hours of testing again crashes with "Finalization 
error".


So InvalidMemoryOperationError means a GC function got called 
while the GC was locked. This is usually because you did an 
allocation inside a destructor.


Finalization error happens when a destructor throws an exception.

Now, many times, trying to throw an exception from inside a 
destructor will first trigger the invalid operation - allocating 
the exception will be an error before the exception actually 
exists. But there are a few ways around this, like preallocating 
or calling a function that uses a statically allocated exception.



Language features that use statically allocated exceptions 
include:


* InvalidMemoryOperationError
* OutOfMemoryError
* SwitchError

There might be more, but this is all I see right now (my process 
btw: search the druntime source code for "staticError", the 
function that makes those. But this is subject to change, so 
first maybe look up the definition of onOutOfMemoryError and see 
the pattern there.)



Of these... well, they are all kinda difficult to cause in a 
destructor.


Are you preallocating something in your code and throwing it in a 
destructor?




Also, what *exactly* is the message you get when the exception 
happens? It should include a line number from druntime as well as 
message from the inner exception that caused it in the first 
place.