Closed Bug 198101 Opened 21 years ago Closed 20 years ago

Click on "Developer Information", and Camino will call SetPort() with a previously deallocated port parameter

Categories

(Camino Graveyard :: General, defect)

PowerPC
macOS
defect
Not set
critical

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: velocio, Assigned: sfraser_bugs)

Details

(Keywords: crash)

User-Agent:       Mozilla/4.0 (compatible; MSIE 5.22; Mac_PowerPC)
Build Identifier: Camino 0.7, build ID 2003030613

I am the Quickdraw engineer in Mac OS X, and get bug reports about crashes of Camino 
in Quickdraw code. The reason is that Camino often sets the current port to an invalid 
port, which has previously been deallocated (closed). On a special debug build of 
Quickdraw that logs OpenCPort/CloseCPort/SetPort calls, includes an IsValidPort() call 
inside SetPort, and sets Handle fields in a deallocated port to 'DEAD', this shows in the 
following (100% reproducible) gdb log. Note that the invalid port does not cause crashes 
right away, but only several minutes later, and often not at all. But with changes in the OS' 
memory allocation/deallocation patterns, the crash can also be consistent and 
unavoidable!

(gdb) r
Starting program: /Volumes/A17/Applications/Camino.app/Contents/MacOS/Camino
Cannot access memory at address 0x9905811c
Temporarily disabling shared library breakpoints: 1
Re-enabling shared library breakpoints: 1
kCGErrorFailure : The function CGContextSaveGState2 is obsolete. Use of this function 
may cause an overall degradation in the performance of this application, or of the system 
as a whole. Please use CGContextSaveGState instead.
### MRJPlugin:  getPluginBundle() here. ###
### MRJPlugin:  CFBundleGetBundleWithIdentifier() succeeded. ###
### MRJPlugin:  CFURLGetFSRef() succeeded. ###
CoreQuickDraw/HighLevel/Ports.c line 1923: OpenCPort 0xe32710
CoreQuickDraw/HighLevel/Ports.c line 1923: OpenCPort 0x2fef890
CoreQuickDraw/HighLevel/Ports.c line 1923: OpenCPort 0x30b5130
CoreQuickDraw/HighLevel/Ports.c line 1923: OpenCPort 0x30e93b0
CoreQuickDraw/HighLevel/Ports.c line 1923: OpenCPort 0x3181df0
kCGErrorFailure : CGContextShowPositionedGlyphs is obsolete; use 
CGContextShowGlyphsWithDeviceAdvances instead.
CoreQuickDraw/HighLevel/Ports.c line 682: CloseCPort 0x30e93b0

Breakpoint 1, SetPort (port=0x30e93b0) at CoreQuickDraw/HighLevel/Ports.c:2213
2213                    QD_DEBUGMSG1("SetPort: port 0x%x INVALID!", (unsigned int)port);

(gdb) bt
#0  SetPort (port=0x30e93b0) at CoreQuickDraw/HighLevel/Ports.c:2213
#1  0x93957520 in -[NSQuickDrawView dealloc] ()
#2  0x003c78e4 in -[ChildView dealloc] ()
#3  0x93678ca8 in -[NSView release] ()
#4  0x90891fc8 in NSPopAutoreleasePool ()
#5  0x908a3414 in __NSFireTimer ()
#6  0x90174edc in __CFRunLoopDoTimer ()
#7  0x901599dc in __CFRunLoopRun ()
#8  0x90192144 in CFRunLoopRunSpecific ()
#9  0x90158d90 in CFRunLoopRunInMode ()
#10 0x93142b5c in RunCurrentEventLoopInMode ()
#11 0x9314d258 in ReceiveNextEventCommon ()
#12 0x9316bf10 in BlockUntilNextEventMatchingListInMode ()
#13 0x9368463c in _DPSNextEvent ()
#14 0x9368f14c in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] 
()
#15 0x936983b4 in -[NSApplication run] ()
#16 0x937b24b8 in NSApplicationMain ()
#17 0x00004ff0 in _start ()
#18 0x00004e70 in start ()

(gdb) p *(_CGrafPtr)port
$1 = {
  device = 13,                                 ## has been overwritten, already!
  portPixMap = 0xca5b0318,      ## See p **(PixMap**)0xca5b0318, below
  portVersion = 9824,
  grafVars = 0x315d940,
  chExtra = 0,
  pnLocHFrac = -32768,
  portRect = {
    top = 0,
    left = 0,
    bottom = 482,
    right = 800
  },
  visRgn = 0x44454144,
  clipRgn = 0x44454144,
  bkPixPat = 0x44454144,
 (...)

(gdb) p **(PixMap**)0xca5b0318
Cannot access memory at address 0xca5b0318



Reproducible: Always

Steps to Reproduce:
1.Start up, http://www.mozilla.org/projects/camino/homepage.html
2.Click on "Developer Information"
3.(there is no step 3!)

Actual Results:  
SetPort(port) gets called with an invalid, previously closed port, down from 
#1  0x93957520 in -[NSQuickDrawView dealloc] ()


Expected Results:  
Don't set to the current port to an invalid port.
When in doubt, call IsValidPort().
If no valid port is available, and the current port has been deallocated, call 
SetPort(NULL)!
Keywords: crash
QA Contact: winnie → petersen
WFM Camino Nightly 2003032008
Is there a way I can debug this without a super-special QuickDraw build? Will it
show up if I use debug libs?
Assignee: saari → sfraser
Status: UNCONFIRMED → NEW
Ever confirmed: true
How to debug: Add "IsValidPort(port)" calls to the SetPort/SetGWorld calls, and watch the DisposePort/DisposeGWorld calls whether they are disposing a port that you just saved as the current port, and are about to restore in SetPort/SetGWorld.You can also add code to all DisposePort/DisposeGWorld calls that wipes out (or sets to something odd) the first 20 bytes or so of the port having been deallocated, which should cause crashes when the invalid port gets used.
Sorry to have ignored this bug for so long, but it looks to me like [NSQuickDrawView dealloc] is doing 
the bad SetPort(). NSQuickDrawView is Apple code.

NSQuickDrawView has some port save/restore logic that isn't well documented, and seems to expect 
QDView lifetimes to be nicely nested. Alas, that's not the case in Camino.
Status: NEW → ASSIGNED
Note also that our NSQuickdrawView subclass's dealloc looks like this:

- (void) dealloc
{
  [super dealloc];    // this sets the current port to _savePort
  SetPort(NULL);      // this is safe on OS X; it will set the port to
                      // an empty fallback port.
}

so we're pretty aware of the bad port issues, and we ensure that the current port isn't left pointing to a 
bad port.
Status update please?
The explanation about NSQuickdrawView's behavior is correct. Whatever the current port was at the 
time NSQuickdrawView gets instantiated, it does get restored by NSQuickdrawView when it gets 
destroyed. If the client has the port deallocated in the meantime (which is legitimate, of course), 
NSQuickdrawView sets an invalid port.
I wish NSQuickdrawView didn't exist ... ;-)
You may close this bug. I filed it because I know there have been some other issues with invalid ports in 
Camino, and I thought this would help track them down.
NSQuickdrawView is the source of many of our headaches:
  bug 159552
  bug 224213 (panther only).
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.