All users were logged out of Bugzilla on October 13th, 2018

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

RESOLVED FIXED

Status

--
critical
RESOLVED FIXED
16 years ago
15 years ago

People

(Reporter: velocio, Assigned: sfraser_bugs)

Tracking

({crash})

Details

(Reporter)

Description

16 years ago
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)!

Updated

16 years ago
Keywords: crash

Updated

16 years ago
QA Contact: winnie → petersen

Comment 1

16 years ago
WFM Camino Nightly 2003032008
(Assignee)

Comment 2

16 years ago
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
(Reporter)

Comment 3

16 years ago
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.
(Assignee)

Comment 4

15 years ago
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
(Assignee)

Comment 5

15 years ago
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.

Comment 6

15 years ago
Status update please?
(Reporter)

Comment 7

15 years ago
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.
(Assignee)

Comment 8

15 years ago
NSQuickdrawView is the source of many of our headaches:
  bug 159552
  bug 224213 (panther only).
Status: ASSIGNED → RESOLVED
Last Resolved: 15 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.