No debugger in threaded mode?!

BlitzMax Forums/BlitzMax Module Tweaks/No debugger in threaded mode?!

GfK(Posted 2010) [#1]
That can't be right, can it? How are you meant to debug threaded code?

Global x:myType = New myType
DebugStop

Type myType
	Field a:Int
	Field b:String
	Field c:Long
End Type

Run that and check the debugger. In single thread mode, you can see the fields in X just fine. In threaded mode, you can't.

This is making it virtually impossible to write threaded code. I have an error somewhere in my code but I have no means of tracing it. Is this how its meant to work??


Dreamora(Posted 2010) [#2]
Thats a core problem of threaded code.
How do you want to stop code in threaded mode?

You stop Thread X
But that won't interest thread Y, Z, A and B

So while you have locked X to inspect it other code continues, generating bugs that otherwise don't exist introduce new sideeffects.


GfK(Posted 2010) [#3]
How do you want to stop code in threaded mode?
Well, you tell me. It just seems senseless that you have to work without a debugger of any kind when using threads. Surely there's a better way? If you could still debug just the main thread, that'd be something.


Dreamora(Posted 2010) [#4]
Up to which degree this could work is something that I can't comment on, only Mark and a handfull of others that have indepth enough knowledge on the related core aspects.


Brucey(Posted 2010) [#5]
I can't see why it would be a problem to lock 1 thread while the others are still running.
It works fine in Java to do that - of course there are two ways to halt execution there with localized breakpoints and whole program "pause" (which stops all threads in their tracks).

If the debug layer is "thread safe", then it could very well work properly.
However, the IDE is not designed to show multiple thread-stacks, so that would need a rewrite.

I haven't looked at what goes on in the appstub recently to see what's going on when threading.


ziggy(Posted 2010) [#6]
Some threaded environments just pause all threads on debugstop, and step-in/out only the thread where the debugstop was executed until a 'continue' is raised. This way all variables, classes, etc are accesible in a ordered way. That usually works well unless you want to test threads sync with the debugger.


Otus(Posted 2010) [#7]
This is a bug in mod/blitz.mod/blitz_gc_ms.c - replace the following
int bbGCValidate( void *p ){
	int r;

	BB_LOCK

	r=testMemBit( p ) ? 1 : 0;

	BB_UNLOCK
	return r;
}

with
int bbGCValidate( void *p ){
	int r;

	BB_LOCK

	r=getBlock( p ) ? 1 : 0;

	BB_UNLOCK
	return r;
}

and everything works the way it should.


GfK(Posted 2010) [#8]
Before I try it, what exactly does that do in laymen's terms?


Otus(Posted 2010) [#9]
Before I try it, what exactly does that do in laymen's terms?

That's the piece of code that validates whether a block of memory is tracked by the GC. The debugger (appstub.mod/debugger.stdio.bmx) uses it to check that the object reference passed to it (e.g. by the IDE) is really an object. As far as I can tell, it is only used by the debugger. The getBlock function calls testMemBit after the correct pointer arithmetic.


GaryV(Posted 2010) [#10]
Before I try it, what exactly does that do in laymen's terms?
It fixes the bug you are reporting?


GfK(Posted 2010) [#11]
It fixes the bug you are reporting?
Oh do stop it.

That's the piece of code that validates whether a block of memory is tracked by the GC. The debugger (appstub.mod/debugger.stdio.bmx) uses it to check that the object reference passed to it (e.g. by the IDE) is really an object. As far as I can tell, it is only used by the debugger. The getBlock function calls testMemBit after the correct pointer arithmetic.
Right, just modified it and it works fine now, for the main thread at least. Should make things a hell of a lot easier. Thanks!

Doesn't directly solve the problem of not being able to debug threads, although its possible to work around that by executing the thread function in the main thread for debugging purposes.

Either way, this is a huge help.


Otus(Posted 2010) [#12]
Doesn't directly solve the problem of not being able to debug threads, although its possible to work around that by executing the thread function in the main thread for debugging purposes.

Ok, I haven't tested this thoroughly, but here's a very simple implementation for debugging non-main threads. It uses thread-local data and probably has way more overhead than the default debugger. Nevertheless, it seems to work fine. If one thread debug-stops, others continue and ignore any debugging.

Add this to mod/brl.mod/appstub.mod named e.g. debugger.stdio2.bmx and change the import in appstub.bmx, but do so at your own risk after backups :)

Edit: Old code, dont use!


And a test program; default debugger doesn't stop, the above modified version should:
SuperStrict

Framework BRL.StandardIO
Import BRL.Threads

Function ThreadFunc:Object(data:Object)
	DebugStop
End Function

TThread.Create(ThreadFunc,Null).Wait



GfK(Posted 2010) [#13]
I'm on the verge of knocking this threading lark on the head.

The code above works fine but when I compile my own game I get the dreaded "EXCEPTION_ACCESS_VIOLATION" and I have no idea why. My game doesn't even begin to run. Yet if I use an unmodified appstub, it compiles and runs OK.

I'm using several third-party mods (MaxMod, TimelineFX, Chaos.Desktopextension) so I don't know if the problem is with one of those, or something else.


Otus(Posted 2010) [#14]
The code above works fine but when I compile my own game I get the dreaded "EXCEPTION_ACCESS_VIOLATION" and I have no idea why. My game doesn't even begin to run. Yet if I use an unmodified appstub, it compiles and runs OK.

Do you mean the code in #12? As I wrote, I didn't really test it much - it's probably to blame for any problems. I'll have to test it with something more complicated.


Otus(Posted 2010) [#15]
I should have at least tested digesteroids, which didn't work... With this it seems to work:



The problem seems to be thread-locals not working early in module init. I suppose this version will also fail to work if any modules launch threads during init...


GfK(Posted 2010) [#16]
Thanks! Seems to be working perfectly now.

This should be officially added to Blitzmax - being able to debug threads is invaluable.


jtfrench(Posted 2011) [#17]
Hi folks,

We're working a pretty massive multithreaded MiniB3D project, and we're getting some pretty strange crashes involving the Blitz sound modules and thread collisions. When debugging though, it seems the debugger is a bit inconsistent.

I searched the forums and this thread sounded pretty relevant to the issues we're going through....we're using BlitzMax 1.41...are these changes still relevant? has the multi-threaded debugger support changed since? If not, we may jump into the deep end and try out this module hacking stuff.

thanks,
jason