I am quite amateur when it comes to development, but I really want to keep GNUMail alive as my primary email client. So bear with me if this analysis is a bit thin.
While debugging why the closing the Compose window (by hitting X or clicking 'Send') generates a SIGSEGV, I found the following and I would like to know your opinions whether this is a bug in GNUstep gui classes or in GNUMail.
First some structures: EditWindow is a subclass of NSWindow EditWindowController is a subclass of NSWindowController.
The controller is has the following initializer, and it is not using NIBs on Linux so the method argument is not important right now:
With this known we know that:
* the EditWindow's delegate is the EditWindowController * the toolbar in the EditWindow has the EditWindowController as delegate.
Now the problem:
When you hit 'Send' or close the window the following deallocation sequence is happening (ordered):
-dealloc in EditWindowController is called. (This goes fine) -dealloc in EditWindow is called and crashes.
The crash is happening when [super dealloc] is called and the following deallocation sequence is happening:
In NSWindow.m:734 -dealloc first thing that is called is [self setToolbar: nil]; It will try to remove the last toolbar view with (a GSWindowDecorationView *_wv;) with removeToolbarView: [_toolbar _toolbarView]. The last method call in removeToolbarView is this:
[self changeWindowHeight: -toolbarViewHeight];
This is calling the follwing to adjust the frame in the NSWindow:
[window setFrame: windowFrame display: YES];
Here is the problem in the setFrame:display method that causes the sigsegv:
Note, at this point _delegate will be 0xdeadface because the EditWindowController has been deallocated and therefore respondsToSelector will crash.
Now, my question is - is this a GNUMail bug (i.e. the NSToolbar should have been deallocated earlier) or is it a problem with the GSWindowDecorationView removeToolbarView? Perhaps there should be a check if the delegate still is valid before calling setFrame?
The workaround is to set NSZombieEnabled to YES, but that will just hide the problem.