Closed
Bug 12139
Opened 25 years ago
Closed 25 years ago
File | Exit throws an assertion.
Categories
(SeaMonkey :: MailNews: Message Display, defect, P3)
Tracking
(Not tracked)
VERIFIED
FIXED
People
(Reporter: skasinathan, Assigned: davidmc)
Details
Overview Description: File | Exit throws an assertion.
Build Date & Platform Bug Found:
8/19/99. windows debug build. I pulled the tree around 10.00 AM.
Steps to Reproduce:
1. Start messenger using Task | Messenger.
2. Do File | Exit. Throws an assertion.
Here is the Stack trace.
NTDLL! 77f7629c()
nsDebug::Assertion(const char * 0x01876c08, const char * 0x01876b24, const char
* 0x01876af4, int 74) line 176 + 13 bytes
mork_assertion_signal(const char * 0x01876c08) line 74 + 31 bytes
morkEnv::NewError(const char * 0x01876ff0) line 362 + 19 bytes
morkStore::CannotAutoAssignAtomIdentityError(morkEnv * 0x04886e10) line 641
morkAtomSpace::MakeBookAtomCopy(morkEnv * 0x04886e10, const morkBigBookAtom &
{...}) line 229 + 9 bytes
morkStore::YarnToAtom(morkEnv * 0x04886e10, const mdbYarn * 0x0012d948) line 719
+ 16 bytes
morkBuilder::OnValue(morkEnv * 0x04886e10, const morkSpan & {...}, const morkBuf
& {...}) line 836 + 16 bytes
morkParser::ReadCell(morkEnv * 0x04886e10) line 565
morkParser::ReadRow(morkEnv * 0x04886e10, int 40) line 651
morkParser::ReadContent(morkEnv * 0x04886e10, unsigned char 1) line 1314
morkParser::ReadGroup(morkEnv * 0x04886e10) line 1115
morkParser::ReadAt(morkEnv * 0x04886e10, unsigned char 0) line 1148
morkParser::ReadContent(morkEnv * 0x04886e10, unsigned char 0) line 1325 + 16
bytes
morkParser::OnPortState(morkEnv * 0x04886e10) line 1359 + 14 bytes
morkParser::ParseLoop(morkEnv * 0x04886e10) line 1415 + 12 bytes
morkParser::ParseMore(morkEnv * 0x04886e10, long * 0x0012da90, unsigned char *
0x04886634, unsigned char * 0x04886635) line 1454
morkThumb::DoMore_OpenFileStore(morkEnv * 0x04886e10) line 432
morkThumb::DoMore(morkEnv * 0x04886e10, unsigned long * 0x0012db2c, unsigned
long * 0x0012db24, unsigned char * 0x0012db30, unsigned char * 0x0012db28) line
352 + 12 bytes
orkinThumb::DoMore(nsIMdbEnv * 0x04883358, unsigned long * 0x0012db2c, unsigned
long * 0x0012db24, unsigned char * 0x0012db30, unsigned char * 0x0012db28) line
225
nsMsgDatabase::OpenMDB(nsMsgDatabase * const 0x04884cb0, const char *
0x04886e88, int 0) line 611 + 46 bytes
nsImapMailDatabase::Open(nsImapMailDatabase * const 0x048841d0, nsIFileSpec *
0x04882c00, int 0, int 0, nsIMsgDatabase * * 0x0012de98) line 89 + 29 bytes
nsImapMailFolder::GetDBFolderInfoAndDB(nsIDBFolderInfo * * 0x0012def4,
nsIMsgDatabase * * 0x0012def0) line 877 + 40 bytes
nsMsgDBFolder::ReadDBFolderInfo(int 0) line 212 + 59 bytes
nsImapMailFolder::UpdateSummaryTotals(nsImapMailFolder * const 0x03b5f87c, int
0) line 653
nsImapMailFolder::GetSubFolders(nsImapMailFolder * const 0x03b5f87c,
nsIEnumerator * * 0x0012dfdc) line 352
nsMsgDBFolder::WriteToFolderCache(nsMsgDBFolder * const 0x03b5f87c,
nsIMsgFolderCache * 0x037caed0) line 391 + 36 bytes
nsMsgDBFolder::WriteToFolderCache(nsMsgDBFolder * const 0x03b5404c,
nsIMsgFolderCache * 0x037caed0) line 419 + 30 bytes
nsMsgIncomingServer::WriteToFolderCache(nsMsgIncomingServer * const 0x037c9970,
nsIMsgFolderCache * 0x037caed0) line 109 + 30 bytes
nsMsgAccountManager::hashTableWriteFolderCache(nsHashKey * 0x037caf30, void *
0x037c9e80, void * 0x037caed0) line 661
_hashEnumerate(PLHashEntry * 0x037c9bd0, int 4, void * 0x0012e0e0) line 85 + 26
bytes
PL_HashTableEnumerateEntries(PLHashTable * 0x037c7780, int (PLHashEntry *, int,
void *)* 0x10014c90 _hashEnumerate(PLHashEntry *, int, void *), void *
0x0012e0e0) line 368 + 15 bytes
nsHashtable::Enumerate(int (nsHashKey *, void *, void *)* 0x015c6610
nsMsgAccountManager::hashTableWriteFolderCache(nsHashKey *, void *, void *),
void * 0x037caed0) line 214 + 20 bytes
nsMsgAccountManager::WriteToFolderCache(nsMsgAccountManager * const 0x037c7810,
nsIMsgFolderCache * 0x037caed0) line 875
nsMsgMailSession::~nsMsgMailSession() line 57
nsMsgMailSession::`scalar deleting destructor'(unsigned int 1) + 15 bytes
nsMsgMailSession::Release(nsMsgMailSession * const 0x037c7910) line 31 + 96
bytes
DeleteEntry(nsHashKey * 0x0012e188, void * 0x037c9150, void * 0x00000000) line
168 + 18 bytes
nsObjectHashtable::RemoveAndDelete(nsHashKey * 0x0012e188) line 370 + 21 bytes
nsServiceManagerImpl::UnregisterService(nsServiceManagerImpl * const 0x00e917c0,
const nsID & {...}) line 356
nsServiceManagerImpl::UnregisterService(nsServiceManagerImpl * const 0x00e917c0,
const char * 0x015ebd5c) line 381
nsServiceManager::UnregisterService(const char * 0x015ebd5c) line 525
nsMessengerBootstrap::Shutdown(nsMessengerBootstrap * const 0x00f35bb0) line 68
+ 11 bytes
nsAppShellService::ShutdownComponent(const nsID & {...}) line 444 + 12 bytes
nsAppShellService::EnumerateComponents(void (const nsID &)* 0x00fb1668
nsAppShellService::ShutdownComponent(struct nsID const &)) line 365
nsAppShellService::Shutdown(nsAppShellService * const 0x00f3dd20) line 487
nsEditorShell::Exit(nsEditorShell * const 0x04414290) line 1077
XPTC_InvokeByIndex(nsISupports * 0x04414290, unsigned int 24, unsigned int 0,
nsXPTCVariant * 0x0012e3f8) line 135
nsXPCWrappedNativeClass::CallWrappedMethod(JSContext * 0x0372e7c0,
nsXPCWrappedNative * 0x04870080, const XPCNativeMemberDescriptor * 0x03fed1b8,
nsXPCWrappedNativeClass::CallMode CALL_METHOD, unsigned int 0, long *
0x011dacec, long * 0x0012e600) line 511 + 44 bytes
WrappedNative_CallMethod(JSContext * 0x0372e7c0, JSObject * 0x02e83928, unsigned
int 0, long * 0x011dacec, long * 0x0012e600) line 130
js_Invoke(JSContext * 0x0372e7c0, unsigned int 0, unsigned int 0) line 654 + 26
bytes
js_Interpret(JSContext * 0x0372e7c0, long * 0x0012ee2c) line 2228 + 15 bytes
js_Invoke(JSContext * 0x0372e7c0, unsigned int 0, unsigned int 0) line 670 + 13
bytes
js_Interpret(JSContext * 0x0372e7c0, long * 0x0012f614) line 2228 + 15 bytes
js_Invoke(JSContext * 0x0372e7c0, unsigned int 1, unsigned int 2) line 670 + 13
bytes
js_InternalCall(JSContext * 0x0372e7c0, JSObject * 0x02dfa4a8, long 48211120,
unsigned int 1, long * 0x0012f754, long * 0x0012f75c) line 747 + 15 bytes
JS_CallFunctionValue(JSContext * 0x0372e7c0, JSObject * 0x02dfa4a8, long
48211120, unsigned int 1, long * 0x0012f754, long * 0x0012f75c) line 2643 + 29
bytes
nsJSEventListener::HandleEvent(nsIDOMEvent * 0x044305a0) line 97 + 34 bytes
nsEventListenerManager::HandleEvent(nsIPresContext & {...}, nsEvent *
0x0012f92c, nsIDOMEvent * * 0x0012f8f4, unsigned int 3, nsEventStatus &
nsEventStatus_eIgnore) line 1110 + 27 bytes
RDFElementImpl::HandleDOMEvent(RDFElementImpl * const 0x03abb160, nsIPresContext
& {...}, nsEvent * 0x0012f92c, nsIDOMEvent * * 0x0012f8f4, unsigned int 1,
nsEventStatus & nsEventStatus_eIgnore) line 2392
nsMenuFrame::Execute() line 938
nsMenuFrame::HandleEvent(nsMenuFrame * const 0x03fcb9e8, nsIPresContext & {...},
nsGUIEvent * 0x0012fba0, nsEventStatus & nsEventStatus_eConsumeDoDefault) line
245
PresShell::HandleEvent(PresShell * const 0x0374fd74, nsIView * 0x03dbaea0,
nsGUIEvent * 0x0012fba0, nsEventStatus & nsEventStatus_eConsumeDoDefault) line
1877 + 38 bytes
nsView::HandleEvent(nsView * const 0x03dbaea0, nsGUIEvent * 0x0012fba0, unsigned
int 8, nsEventStatus & nsEventStatus_eConsumeDoDefault, int & 0) line 835
nsView::HandleEvent(nsView * const 0x0374e1f0, nsGUIEvent * 0x0012fba0, unsigned
int 28, nsEventStatus & nsEventStatus_eConsumeDoDefault, int & 0) line 820
nsViewManager::DispatchEvent(nsViewManager * const 0x0374e410, nsGUIEvent *
0x0012fba0, nsEventStatus & nsEventStatus_eConsumeDoDefault) line 1611
HandleEvent(nsGUIEvent * 0x0012fba0) line 67
nsWindow::DispatchEvent(nsWindow * const 0x03dba174, nsGUIEvent * 0x0012fba0,
nsEventStatus & nsEventStatus_eIgnore) line 498 + 10 bytes
nsWindow::DispatchWindowEvent(nsGUIEvent * 0x0012fba0) line 523
nsWindow::DispatchMouseEvent(unsigned int 301, nsPoint * 0x00000000) line 3271 +
21 bytes
ChildWindow::DispatchMouseEvent(unsigned int 301, nsPoint * 0x00000000) line
3466
nsWindow::ProcessMessage(unsigned int 514, unsigned int 0, long 24182853, long *
0x0012fdd4) line 2539 + 24 bytes
nsWindow::WindowProc(HWND__ * 0x03690be6, unsigned int 514, unsigned int 0, long
24182853) line 571 + 27 bytes
USER32! 77e71820()
Updated•25 years ago
|
Assignee: bienvenu → davidmc
Comment 1•25 years ago
|
||
this is a mork problem, perhaps having to do with incremental writing.
This bug report is evidence of memory corruption, because the only
way that assertion can fire is if mStore_CanAutoAssignAtomIdentity
is false, and this is never true after you have successfully gotten
a store from Mork.
This is infrastructure for a feature that is not being used yet, so
having it go belly up means that somebody stepped on the byte in
the store object that keeps this boolean state.
One of two things should be true: 1) the bug is not reproducible
because the memory corruption was transient, or 2) somebody is
corrupting memory the same way each time, due to recent changes
in the tree.
Putting a watch on that byte would be informative; I don't have a
build that runs since I'm in the middle of mucking with my tree and
Mork won't build for me. There is nothing for me to fix in Mork,
but if I had free time I could sit and watch who steps on that byte.
Would it be useful for you to sit with Suresh for a few minutes to see this
David?
Yes, but only if we can set a data breakpoint on the morkStore slot
mStore_CanAutoAssignAtomIdentity, to see the memory corruption.
Suresh - if you can do as David suggests, pls work with him on this. Thanks.
David Bienvenu reasoned out that this is likely not memory corruption,
since the relevant boolean starts at false, and only becomes true after
parsing is done; so this bug means parsing the file was unhappy. I need
a file to load to see what happens -- emailing one to me works best.
David B says he can get me one after he builds, but it's fine if someone
beats he to the punch. (And I need to build myself before I can run.)
So the code doesn't like something about the file being parsed; it could
be I'm writing it wrong or reading it wrong. Or less likely, the file
could be corrupt, but I don't expect that. So far I'm thinking maybe I
fail to write a atom def in a dict before some literat string appears.
davidmc - did you get what you need to look further into this bug? Thanks.
Suresh reported a strange Mork bug, which David Bienvenu tracked down in
a debugger for me (see http://bugzilla.mozilla.org/show_bug.cgi?id=12139).
I have a relatively easy fix, but I'm trying to come up with a rational
explanation that demonstrates why this very non-intuitive effect is a
natural result of the differences in reference models used by the
runtime and by the serialized text format under incremental updating.
Someone maintaining Mork, or anyone developing an entirely different
kind of system, but along the same general lines, would want to know
exactly why this situation can arise. The logic seems pretty edgy.
The cause of the problem was this: when putting a new string value as
an atom into a row's cell, we cut any old atom that once lived there.
As it happened, I was keeping track of how many times an atom was
referenced, so I could delete it at zero refs. And I was doing this
while parsing a Mork file, which incrementally updated a row, putting
a new atom value in place of an old one. This caused a tenuous chain
of circumstances about three levels removed which caused an assert.
The problem would go away if we always kept atoms, even at zero refs,
and just let them get collected only during compress commits. But it
would also go away if we merely avoided zapping them at zero refs
while parsing, but permitted them to zap later after a store opens.
This rest of this explains exactly what was wrong. It's interesting
in a hairy kind of way; you'd want to know about this case if you
were toubleshooting weird text parsing errors involving identity.
Here is a Mork fragment which might now fail when parsed:
<(666=6)> // this dict defines hex 0x666 to identify string "6"
[500:m (^90=6)] // row 500:m has a column ^90 containing "6"
@$${8{@ // beginning of transaction 0x8
<(444=4)> // this dict defines hex 0x444 to identify string "4"
[500:m (^90=4)] // change value of col ^90 in row 500:m to "4"
[600:m (^90=6)] // set value of col ^90 in row 600:m to "6"
@$$}8}@ // end of transaction 0x8
Presumably string "6" is entered in the dict at first because it
has never been written before, but we want it defined before first
use in row 500:m that follows. This means the atom in that cell
of the row has but a single reference.
(Note the reason we write a value as "=6" instead of using "^666"
is because the former is shorter and makes the file smaller. We
want strings to have well-defined atom identity token numbers, but
we can use the shorter representation in actual usage; when parsed,
we look up the string in the dict and find the atome token ID, and
that is why thy atom had better appear in the dict before usage.)
So in the subsequent incremental update within transaction 8, when
we change the value of col ^90 in row 500:m to "4", this causes the
last ref to atom 0x666 to go away, and it gets deleted so it is no
longer in the atom dict.
But then the very next row 600:m puts string "6" into col ^90 and
we cannot find the associated atom in the dict while parsing, and
this is where the assert comes from when opening the store, because
every string used must already be in the atom dict.
(The reason every atom must already be in the dict is to avoid any
event of auto-ID assignment that is followed later by explicit ID
assignment. If we saw "6" and could not find it in the dict, and
so assigned next ID 0x76548, and then later saw <(666=6)> which
gives string "6" an ID explicitly, we'd then have a conflict. We
might fix this by replacing the 0x76548 ID with 0x666, but this
would tend to drop 0x76548 on the floor unused, with a net effect
of consuming the ID space faster than necessary. It's hard to put
the ID counter backward in time when it allocates a mixed sequence
of IDs that do and don't get used.)
So how did the Mork text file get that way in the first place? Why
did the second use of "6" not get a new ID at runtime, so that the
file simply redefined "6" to use ID 0x76548 before use in row 600:m?
Well, that probably did happen at runtime, but the Mork file could
still be written the way we say because the count of references at
runtime might not correspond to the count of atom refs as they seem
when parsing the file in linear sequence. And this might interact
with the fact that tables and rows get written in hash table order
(which is pseudo-random), and this can cause refcounts of atoms to
hit zero or not <em>depending on the order of writing</em>. Hmmm.
After a store opens, we blithely auto-assign atom IDs whenever new
atom values are needed. But when parsing a Mork file to prepare a
store to be opened, we want to assert when auto-assignment happens
because this shows we failed in our invariant that enforces all
atoms are written in a dict before they appear in usage.
Anyway, the Mork text format tends to assume that anything before a
point in the text still exists, unless an explicit even happens to
cut all content from a row or table. But the observed bug involves
the death of an atom as a mere side effect of putting new content
into a row, after the atom gets defined in a dict. All by itself,
this seems questionable.
So the best fix for this bug might involve turning off atom garbage
collection at zero refs when still parsing a file. Or if that is
at all hard to determine and control, then never collecting an atom
would be second best. (And then atoms would be collected during a
compress commit, since they would not be written unless in some row.)
David Mc
Assignee | ||
Comment 10•25 years ago
|
||
When I saw I was cutting the old atom, I only had to reason out why
I was doing that, and what the bad effects could be. I posted a longish
post explaining in the newsgroup.
Here is the second best fix as a temporary band-aid, until I do the
better fix by only during it off when in the mode of parsing a file.
This just comments out the code which would destory the atom on zero
refs. I expect it should be okay to have the atom hang around with
zero 'cell uses' since this is mostly advisory information.
void
morkCell::SetAtom(morkEnv* ev, morkAtom* ioAtom, morkPool* ioPool)
{
morkAtom* oldAtom = mCell_Atom;
if ( oldAtom != ioAtom ) // ioAtom is not already installed in this cell?
{
if ( oldAtom )
{
mCell_Atom = 0;
if ( oldAtom->CutCellUse(ev) == 0 )
{
// if ( ioPool )
// {
// if ( oldAtom->IsBook() )
// ((morkBookAtom*) oldAtom)->CutBookAtomFromSpace(ev);
//
// ioPool->ZapAtom(ev, oldAtom);
// }
// else
// ev->NilPointerError();
}
}
if ( ioAtom )
ioAtom->AddCellUse(ev);
mCell_Atom = ioAtom;
}
}
Assignee | ||
Comment 11•25 years ago
|
||
No, I guess that is the permanent fix. We can't allow collection after
the store is open, because then string re-use gets a new ID, and then
that string gets two IDs in the Mork file when written incrementally,
which sounds like a bad idea.
Comment 12•25 years ago
|
||
I'm not seeing this now. Is this fixed or worksforme?
Status: NEW → RESOLVED
Closed: 25 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 13•25 years ago
|
||
This is fixed; guess I'd better clean up my bug list.
Reporter | ||
Comment 15•25 years ago
|
||
Marking this as Verified.
Updated•20 years ago
|
Product: Browser → Seamonkey
You need to log in
before you can comment on or make changes to this bug.
Description
•