Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5187

PostPosted: Sun Nov 04, 2007 12:18 am   

[2.10] UNVAR crash (not thread safe)
 
I initially tested this with a longer procedure that produced a crash at a different point, but I haven't been able to replicate that crash point. I also had the final step not cause a crash in some of tests, but repeating that step soon caused a crash.

Procedure
1. Launch CMud
2. Close Sessions window (ESC)
3. Enter at the command line
Code:
#WHILE 1 {#ADD a 1}

4. Hit SHIFT-ESC to put the while into the background
5. Enter at the command line
Code:
#UNVAR a


The first crash is the replicatable one. I am also including the one I could not replicate, which appears to be a timing issue.
Code:
date/time         : 2007-11-03, 20:30:12, 39ms
operating system  : Windows XP Service Pack 2 build 2600
system language   : English
system up time    : 15 days 12 hours
program up time   : 43 seconds
processor         : AMD Athlon(tm) Processor
physical memory   : 165/383 MB (free/total)
free disk space   : (C:) 14.90 GB
display mode      : 1024x768, 32 bit
process id        : $633c
allocated memory  : 42.87 MB
executable        : cMUD.exe
exec. date/time   : 2007-11-02 17:51
version           : 2.10.0.0
madExcept version : 3.0b
callstack crc     : $7bb5fe5f, $84a7275e, $e6ec8a1e
count             : 3
exception number  : 1
exception class   : EAccessViolation
exception message : Access violation at address 00D32045 in module 'cMUD.exe'. Read of address 0000005C.

untitled Comline ($8a20):
00d32045 +015 cMUD.exe PrefDat    7806  +1 PrefRec.GetOption
00d3656c +0f8 cMUD.exe PrefDat    9355  +7 PrefRec.LoadCache
00d36379 +015 cMUD.exe PrefDat    9301  +1 PrefRec.GetArgList
00d36857 +023 cMUD.exe PrefDat    9408  +1 PrefRec.SetArgList
00d46836 +486 cMUD.exe CodeExec   1712 +86 HandleAssign
00d48d36 +626 cMUD.exe CodeExec   2417 +84 HandleCom
00d4a9e6 +5b2 cMUD.exe CodeExec   2951 +96 TCodeExec.InternalExecute
00d42341 +071 cMUD.exe CodeExec    451  +9 TCodeExec.Execute
00d48a06 +2f6 cMUD.exe CodeExec   2360 +27 HandleCom
00d4a9e6 +5b2 cMUD.exe CodeExec   2951 +96 TCodeExec.InternalExecute
00d4227e +05e cMUD.exe CodeExec    427  +8 TCodeExec.Execute
00c4c49c +154 cMUD.exe CodeThread 1534 +21 TRunCodeThread.Run
00903bec +138 cMUD.exe IdThread    360 +47 TIdThread.Execute
0047d9da +036 cMUD.exe Classes    9372  +7 ThreadProc
00405acc +028 cMUD.exe System              ThreadWrapper

Main ($6334):
7c90eb94 +00 ntdll.dll                   KiFastSystemCallRet
0052edb9 +1d cMUD.exe     Forms 6862  +2 TApplication.ProcessMessage
0052ee8f +0f cMUD.exe     Forms 6892  +1 TApplication.HandleMessage
0052f12a +a6 cMUD.exe     Forms 6976 +16 TApplication.Run
00dbda08 +88 cMUD.exe     CMUD   344 +18 initialization
7c91312f +69 ntdll.dll                   RtlUnicodeStringToAnsiString
7c812907 +b6 kernel32.dll                GetVersionExA
Code:
date/time         : 2007-11-03, 20:22:04, 257ms
computer name     : CHAOTIC
user name         : James Dean <admin>
operating system  : Windows XP Service Pack 2 build 2600
system language   : English
system up time    : 15 days 12 hours
program up time   : 1 minute 46 seconds
processor         : AMD Athlon(tm) Processor
physical memory   : 180/383 MB (free/total)
free disk space   : (C:) 14.90 GB
display mode      : 1024x768, 32 bit
process id        : $c54c
allocated memory  : 28.62 MB
executable        : cMUD.exe
exec. date/time   : 2007-11-02 17:51
version           : 2.10.0.0
madExcept version : 3.0b
callstack crc     : $47a2947b, $7eed0c3a, $7eed0c3a
exception number  : 1
exception class   : EDatabaseError
exception message : MemCursor: Dataset is not in edit mode.

Main ($2e20):
006400fe +006a cMUD.exe     DB                  2350    +2 DatabaseError
00663392 +006a cMUD.exe     kbmMemTable        11007    +5 TkbmCustomMemTable.SetFieldData
00650593 +0047 cMUD.exe     DB                  9250    +2 TDataSet.SetFieldData
008deaa1 +0029 cMUD.exe     ZAbstractRODataset  1170    +3 TZAbstractRODataset.SetFieldData
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
006452fc +010c cMUD.exe     DB                  4447   +14 TStringField.SetAsString
0065051c +0100 cMUD.exe     DB                  9238   +16 TDataSet.GetFieldData
00650463 +0047 cMUD.exe     DB                  9224    +2 TDataSet.GetFieldData
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
006452fc +010c cMUD.exe     DB                  4447   +14 TStringField.SetAsString
00650463 +0047 cMUD.exe     DB                  9224    +2 TDataSet.GetFieldData
00505f93 +01df cMUD.exe     Controls            4645   +53 TControl.WndProc
00505c9e +0036 cMUD.exe     Controls            4552    +5 TControl.Perform
0050ccf3 +0037 cMUD.exe     Controls            7721    +3 TWinControl.CMInvalidate
00505f93 +01df cMUD.exe     Controls            4645   +53 TControl.WndProc
004966a8 +000c cMUD.exe     SyncObjs             222    +1 TCriticalSection.Leave
0065d369 +0009 cMUD.exe     kbmMemTable         6034    +5 TkbmCommon.Unlock
00663594 +026c cMUD.exe     kbmMemTable        11083   +81 TkbmCustomMemTable.SetFieldData
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
006452fc +010c cMUD.exe     DB                  4447   +14 TStringField.SetAsString
00650463 +0047 cMUD.exe     DB                  9224    +2 TDataSet.GetFieldData
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
0048593b +001b cMUD.exe     Graphics            1380    +1 TGraphicsObject.Changed
00650463 +0047 cMUD.exe     DB                  9224    +2 TDataSet.GetFieldData
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
006452fc +010c cMUD.exe     DB                  4447   +14 TStringField.SetAsString
004d706e +0d12 cMUD.exe     ComCtrls           14625  +276 TCustomListView.CNNotify
004d6c1b +08bf cMUD.exe     ComCtrls           14525  +176 TCustomListView.CNNotify
7c912c94 +0013 ntdll.dll                                   LdrFindResource_U
77d5029f +0078 USER32.dll                                  WCSToMBEx
77d6ecc8 +0030 USER32.dll                                  LoadStringA
0082721e +0032 cMUD.exe     StDict               546    +5 TStDictionary.DoEqual
0082727c +0050 cMUD.exe     StDict               561    +8 TStDictionary.dyFindNode
008274e1 +0035 cMUD.exe     StDict               680    +5 TStDictionary.Exists
0064405f +008b cMUD.exe     DB                  4003    +4 TField.SetData
00645b92 +006a cMUD.exe     DB                  4646    +4 TIntegerField.SetAsInteger
006429c4 +0088 cMUD.exe     DB                  3450    +4 TField.AssignValue
00661e8f +00ab cMUD.exe     kbmMemTable         9725   +20 TkbmCustomMemTable.FindKey
00d24ce1 +005d cMUD.exe     PrefDat             1913    +8 PrefRec.Remove
00d24be3 +000f cMUD.exe     PrefDat             1883    +1 PrefRec.Destroy
00d25752 +0032 cMUD.exe     PrefDat             2244    +4 VarRec.Destroy
00404be0 +0008 cMUD.exe     System                         TObject.Free
00cc5852 +96b6 cMUD.exe     MAIN               18055 +1668 HandleCase
00cc6d3f +007f cMUD.exe     MAIN               18181   +11 TMUDForm.ExecCommand
00c4b1ac +0034 cMUD.exe     CodeThread          1076    +2 TRunCodeThread.DoExecCommand
0047d901 +0101 cMUD.exe     Classes             9339   +22 CheckSynchronize
00c4a3ac +0094 cMUD.exe     CodeThread           435   +15 MsgWaitForSingleObject
00c4a4fd +0029 cMUD.exe     CodeThread           510    +4 WaitForThread
00c97c52 +012e cMUD.exe     MAIN                6005   +32 TMUDForm.ExecThread
00c987e2 +03c6 cMUD.exe     MAIN                6213   +44 TMUDForm.NewProcessStr
00c977be +0026 cMUD.exe     MAIN                5899    +2 TMUDForm.ProcessStr
00c9729a +004a cMUD.exe     MAIN                5774   +12 TMUDForm.ParseCommand
00ca5be3 +0223 cMUD.exe     MAIN               11189   +34 TMUDForm.Command
00ca6f14 +0250 cMUD.exe     MAIN               11538   +37 TMUDForm.FormKeyDown
00ccdf26 +0012 cMUD.exe     MAIN               20058    +1 TMUDForm.UserInKeyDown
0050b5a0 +0030 cMUD.exe     Controls            7026    +1 TWinControl.KeyDown
009aa1be +0012 cMUD.exe     RVScroll             548    +1 TRVScroller.KeyDown
00958dc5 +0011 cMUD.exe     RichView            1842    +1 TCustomRichView.KeyDown
0093539c +0090 cMUD.exe     RVEdit              1625   +14 TCustomRichViewEdit.KeyDown
0050b618 +006c cMUD.exe     Controls            7043   +10 TWinControl.DoKeyDown
0050b646 +0012 cMUD.exe     Controls            7052    +1 TWinControl.WMKeyDown
00935275 +01d5 cMUD.exe     RVEdit              1591   +36 TCustomRichViewEdit.WMKeyDown
00505c9e +0036 cMUD.exe     Controls            4552    +5 TControl.Perform
0050c3c9 +00dd cMUD.exe     Controls            7471   +18 TWinControl.CNKeyDown
00505f93 +01df cMUD.exe     Controls            4645   +53 TControl.WndProc
00509cc2 +018e cMUD.exe     Controls            6342   +33 TWinControl.WndProc
00509894 +0034 cMUD.exe     Controls            6237    +3 TWinControl.MainWndProc
0047fef8 +0014 cMUD.exe     Classes            10966    +8 StdWndProc
77d4bcc7 +000a USER32.dll                                  DispatchMessageA
0052ee48 +00ac cMUD.exe     Forms               6873   +13 TApplication.ProcessMessage
0052ee8f +000f cMUD.exe     Forms               6892    +1 TApplication.HandleMessage
0052f12a +00a6 cMUD.exe     Forms               6976   +16 TApplication.Run
00dbda08 +0088 cMUD.exe     CMUD                 344   +18 initialization
7c91312f +0069 ntdll.dll                                   RtlUnicodeStringToAnsiString
7c812907 +00b6 kernel32.dll                                GetVersionExA
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Tech
GURU


Joined: 18 Oct 2000
Posts: 2733
Location: Atlanta, USA

PostPosted: Sun Nov 04, 2007 7:44 am   
 
Confirmed.
_________________
Asati di tempari!
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Nov 05, 2007 5:50 pm   
 
Added to bug list. Probably effects some other #UN commands as well.
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Wed Nov 14, 2007 8:51 pm   
 
As I thought, all of the #UN... commands are effected by this problem. And this one is a real problem to fix.

The problem is that the #UNVAR command is freeing the internal record for the variable and deleting it from the database. But a thread running in the background might have it's own reference pointing to this internal record. So now suddenly the variable reference in the background thread is pointing to freed memory, causing all sorts of crashes.

This is one thing I've always hated about memory management. It would be nice if the Free routine could somehow mark the memory as freed so that you could trap this in any other access to that part of memory. But since garbage collection could re-use that memory, the background thread pointer might actually point to valid memory...it just isn't the memory used by the variable anymore.

To make matters worse, Windows can switch threads at any time. So anyplace in my code that I have something like this:

Obj := FindVar( VarName)
do something with Obj.Value

then between these two statements, Windows could switch threads and execute an #UNVAR command, which now causes the Obj pointer to be invalid. The above example would be relatively easy to protect with a critical section. But there are other cases that do stuff like "Obj.Execute" to execute an alias reference, and then later access another property of Obj. And I can't put a section around all of that, because "Execute" is something that could take a long time and call all sorts of other routines, which would deadlock the critical section.

I could implement a "deleted objects list" that would keep track of what references are no longer valid. But then I'd have to change *every* reference to the objects to something that searched this list, and this would cause a huge performance decrease.

This is very similar to a past problem we had where a setting would put a refresh message into the Windows message queue, and then the setting was removed before the message was processed. But the solution to this was to delete the refresh message from the queue when the setting was deleted. The #UNVAR case is more complicated and there aren't any Windows messages involved. It's really more of a classic case of two threads accessing the same resource, and one thread deciding to destroy the object.

What I guess I'll need to do is implement a reference counting system for these objects. Then somehow I'll mark an object as "inuse" and then unmark it when I'm done. The Free routine will check to see if the object is in use and just mark it as deleted. Then, when the object's inuse count hits zero, the object will delete itself if needed. But this is going to be very time consuming to implement since I'll have to check *every* access I make to objects that might be freed by the #UN commands. There isn't any way to implement it transparently within the current class code.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net