[M3devel] help debugging Juno..sanity check?
Tony Hosking
hosking at cs.purdue.edu
Tue Sep 29 15:49:19 CEST 2009
OK, remind me again what happens with @M3nogc. That will prevent
movement, and should allow you to protect state as you originally
intended, without worrying about it being GC'd or moved..
From what you are saying though, it appears that even with @M3nogc
the corruption is not deterministic. Which does make it tricky to
nail down where it occurs.
On 29 Sep 2009, at 01:39, Jay K wrote:
> oops, thanks, I forgot gc is compacting.
>
> I don't see how to use a hardware breakpoint,
> the corruption seems to always move around.
>
> This is an attempt to set a hardware breakpoint programmatically based
> on what the runtime addresses happen to be.
>
> I do know these bytes are getting overwritten.
> If I assert they are zero in Join, inevitably the assert fails.
>
> I think I might try to vary the Juno pixmaps, see if the altered
> data appears in the corruption, try to prove, as it appears,
> that the corruption is pixmap data.
>
> Thanks,
> - Jay
>
>
>
> From: hosking at cs.purdue.edu
> To: jay.krell at cornell.edu
> Date: Mon, 28 Sep 2009 10:04:55 -0400
> CC: m3devel at elegosoft.com
> Subject: Re: [M3devel] help debugging Juno..sanity check?
>
> Huh? I don't understand the point of all of this. Threads can be
> moved by the GC, even if referenced from globals. The only way to
> prevent a thread moving is to keep a reference to it on some thread
> stack. (I still don't know what you are trying to achieve -- why
> not use a hardware breakpoint in the debugger?). That's how I found
> the race in ScrollerVBTClass.m3.
>
> On 28 Sep 2009, at 09:11, Jay K wrote:
>
> So, I know that ThreadWin32.T instances are prone to being
> overwritten.
>
> So I did this:
>
>
> T = BRANDED "Thread.T Win32-1.0" OBJECT
> > pad1: ARRAY [0..16_1000] OF CHAR;
> > protect: ARRAY [0..16_1] OF CHAR;
> > pad2: ARRAY [0..16_1000] OF CHAR;
>
> And then there are two occurences of NEW(T):
>
>
> next_self := NEW(T);
> > Protect(next_self);
>
>
> PROCEDURE CreateT (act: Activation): T =
> (* LL = 0, because allocating a traced reference may cause
> the allocator to start a collection which will call
> "SuspendOthers"
> which will try to acquire "activeMu". *)
> VAR t := NEW(T, act := act);
> BEGIN
> > Protect(t);
>
>
> PROCEDURE Protect(t: T)=
> VAR old: WinDef.DWORD;
> BEGIN
> EVAL WinBase.VirtualProtect(LOOPHOLE(ADR(t.protect), SIZE_T), 1,
> PAGE_READONLY, ADR(old));
> END Protect;
>
>
> This should catch any writes to these fields.
>
>
> Now, a thread can be garbage collected and reused.
> And I'd want to unprotect this memory.
> Or prevent the garbage collector from deciding any thread is garbage.
> Second option seems easier and suffices.
>
>
> So:
>
>
> VAR
> threads: ARRAY[0..2000] OF T; (* big enough for our purposes *)
> threadCount: INTEGER;
>
>
> and more completely:
>
> PROCEDURE Protect(t: T)=
> VAR old: WinDef.DWORD;
> BEGIN
> EVAL WinBase.VirtualProtect(LOOPHOLE(ADR(t.protect), SIZE_T), 1,
> PAGE_READONLY, ADR(old));
> RTIO.PutInt(threadCount);
> RTIO.PutText(" ");
> RTIO.PutAddr(ADR(threads));
> RTIO.PutText(" ");
> RTIO.PutAddr(ADR(t.protect));
> RTIO.PutText("\n");
> threads[threadCount] := t;
> INC(threadCount);
> END Protect;
>
>
> And just in case, I emptied out the FreeSlot function.
>
>
> But yet I get:
>
> 0 0xe2abe0 0x1141021
> 1 0xe2abe0 0x114b429
> 2 0xe2abe0 0x11a2311
> 3 0xe2abe0 0x11a48b1
> 4 0xe2abe0 0x11ab499
> 5 0xe2abe0 0x12e9f11
> 6 0xe2abe0 0x12d211d
> 7 0xe2abe0 0x11bd691
> 8 0xe2abe0 0x11d1011
> 9 0xe2abe0 0x11d3e2d
> 10 0xe2abe0 0x11d6759
> 11 0xe2abe0 0x11d8bd1
> 12 0xe2abe0 0x12089f1
> 13 0xe2abe0 0x1211455
> 14 0xe2abe0 0x12138cd
> 15 0xe2abe0 0x1215ecd
> 16 0xe2abe0 0x12184cd
> 17 0xe2abe0 0x121bcd5
> 18 0xe2abe0 0x121e35d
> Grow (0x210000) => 0x2120000 total: 4.1M span: 17.9M density:
> 23%
> (b60.9d4): Access violation - code c0000005 (first chance)
> First chance exceptions are reported before any exception handling.
> This exception may be expected and handled.
> eax=011b0000 ebx=00010000 ecx=00000060 edx=00000000 esi=011b0000
> edi=011bd000
> eip=78545e37 esp=01cae5ec ebp=01cae5f0 iopl=0 nv up ei pl nz
> na pe nc
> cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
> efl=00010206
> MSVCR90!fastzero_I+0x20:
> 78545e37 660f7f07 movdqa xmmword ptr [edi],xmm0 ds:
> 0023:011bd000=0000000
> 0000000000000000000000000
> 0:003> k
> ChildEBP RetAddr
> 01cae5f0 78545ea9 MSVCR90!fastzero_I+0x20
> 01cae610 005dad48 MSVCR90!_VEC_memzero+0x36
> 01cae634 005d1f34 m3core!RTMisc__Zero+0x1f
> 01cae68c 005c8191 m3core!RTHeapRep__LongAlloc+0xf3
> 01cae6d8 005c7793 m3core!RTAllocator__AllocTraced+0xec
> 01cae70c 005c728d m3core!RTAllocator__GetTracedObj+0x8c
> 01cae730 005d07d9 m3core!RTHooks__AllocateTracedObj+0x15
> 01cae784 005d033f m3core!RTCollector__CollectSomeInStateZero+0x45e
> 01cae798 005cffd6 m3core!RTCollector__CollectSome+0x6e
> 01cae7dc 005c817c m3core!RTHeapRep__CollectEnough+0x9b
> 01cae81c 005c7d06 m3core!RTAllocator__AllocTraced+0xd7
> 01cae858 005c7348 m3core!RTAllocator__GetOpenArray+0x97
> 01cae880 00f9f50d m3core!RTHooks__AllocateOpenArray+0x19
> 01cae930 00f9f201 m3ui!WinScrnPixmap__PixmapFromRaw__ConvertColor+0x8f
> 01cae958 00f9e22f m3ui!WinScrnPixmap__PixmapFromRaw+0x71
> 01cae9ac 00eb4121 m3ui!WinScrnPixmap__Load+0x320
> 01caeee4 00eb298d m3vbtkit!Image__ScaleRaw+0xb30
> 01caef44 00fb2b72 m3vbtkit!Image__ApplyScaled1+0x166
> 01caef70 00fc0af8 m3ui!VBTRep__PixmapApply+0xbf
> 01caefcc 00fa6766 m3ui!Palette__ResolvePixmap+0x7db
> 0:003> r edi
> edi=011bd000
> 0:003>
>
>
> What am I confused about?
>
> Why does it seem that even if I store some pointers in globals, they
> are getting garbage collected and reused?
>
> I should debug BuildGlobalMap??
>
> - Jay
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20090929/178ee32f/attachment-0002.html>
More information about the M3devel
mailing list